mysql的学习要点_MySQL中的联合索引的学习要点总结

MySQL中的联合索引的学习要点总结

联合索引又叫复合索引。对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。

两个或更多个列上的索引被称作复合索引。

利用索引中的附加列,您可以缩小搜索的范围,但使用一个具有两列的索引 不同于使用两个单独的索引。复合索引的结构与电话簿类似,人名由姓和名构成,电话簿首先按姓氏对进行排序,然后按名字对有相同姓氏的人进行排序。如果您知 道姓,电话簿将非常有用;如果您知道姓和名,电话簿则更为有用,但如果您只知道名不姓,电话簿将没有用处。

所以说创建复合索引时,应该仔细考虑列的顺序。对索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引非常有用;仅对后面的任意列执行搜索时,复合索引则没有用处。

如:建立 姓名、年龄、性别的复合索引。

create table test(

a int,

b int,

c int,

KEY a(a,b,c)

);

复合索引的建立原则:

如果您很可能仅对一个列多次执行搜索,则该列应该是复合索引中的第一列。如果您很可能对一个两列索引中的两个列执行单独的搜索,则应该创建另一个仅包含第二列的索引。

如上图所示,如果查询中需要对年龄和性别做查询,则应当再新建一个包含年龄和性别的复合索引。

包含多个列的主键始终会自动以复合索引的形式创建索引,其列的顺序是它们在表定义中出现的顺序,而不是在主键定义中指定的顺序。在考虑将来通过主键执行的搜索,确定哪一列应该排在最前面。

请注意,创建复合索引应当包含少数几个列,并且这些列经常在select查询里使用。在复合索引里包含太多的列不仅不会给带来太多好处。而且由于使用相当多的内存来存储复合索引的列的值,其后果是内存溢出和性能降低。

复合索引对排序的优化:

复合索引只对和索引中排序相同或相反的order by 语句优化。

在创建复合索引时,每一列都定义了升序或者是降序。如定义一个复合索引:

CREATE INDEX idx_example

ON table1 (col1 ASC, col2 DESC, col3 ASC)

其中 有三列分别是:col1 升序,col2 降序, col3 升序。现在如果我们执行两个查询

1:

Select col1, col2, col3 from table1 order by col1 ASC, col2 DESC, col3 ASC

和索引顺序相同

2:

Select col1, col2, col3 from table1 order by col1 DESC, col2 ASC, col3 DESC

和索引顺序相反

查询1,2 都可以别复合索引优化。

如果查询为:

Select col1, col2, col3 from table1 order by col1 ASC, col2 ASC, col3 ASC

排序结果和索引完全不同时,此时的查询不会被复合索引优化。

查询优化器在在where查询中的作用:

如果一个多列索引存在于 列 Col1 和 Col2 上,则以下语句:Select * from table where col1=val1 AND col2=val2 查询优化器会试图通过决定哪个索引将找到更少的行。之后用得到的索引去取值。

1. 如果存在一个多列索引,任何最左面的索引前缀能被优化器使用。所以联合索引的顺序不同,影响索引的选择,尽量将值少的放在前面。

如:一个多列索引为 (col1 ,col2, col3)

那么在索引在列 (col1) 、(col1 col2) 、(col1 col2 col3) 的搜索会有作用。

SELECT * FROM tb WHERE col1 = val1

SELECT * FROM tb WHERE col1 = val1 and col2 = val2

SELECT * FROM tb WHERE col1 = val1 and col2 = val2 AND col3 = val3

2. 如果列不构成索引的最左面前缀,则建立的索引将不起作用。

如:

SELECT * FROM tb WHERE col3 = val3

SELECT * FROM tb WHERE col2 = val2

SELECT * FROM tb WHERE col2 = val2 and col3=val3

3. 如果一个 Like 语句的查询条件不以通配符起始则使用索引。

如:%车 或 %车% 不使用索引。

车% 使用索引。

索引的缺点:

1. 占用磁盘空间。

2. 增加了插入和删除的操作时间。一个表拥有的索引越多,插入和删除的速度越慢。如 要求快速录入的系统不宜建过多索引。

下面是一些常见的索引限制问题

1、使用不等于操作符(<>, !=)

下面这种情况,即使在列dept_id有一个索引,查询语句仍然执行一次全表扫描

select * from dept where staff_num <> 1000;

但是开发中的确需要这样的查询,难道没有解决问题的办法了吗?

有!

通过把用 or 语法替代不等号进行查询,就可以使用索引,以避免全表扫描:上面的语句改成下面这样的,就可以使用索引了。

select * from dept shere staff_num < 1000 or dept_id > 1000;

2、使用 is null 或 is not null

使用 is null 或is nuo null也会限制索引的使用,因为数据库并没有定义null值。如果被索引的列中有很多null,就不会使用这个索引(除非索引是一个位图索引,关于位图索引,会在以后的blog文章里做详细解释)。在sql语句中使用null会造成很多麻烦。

解决这个问题的办法就是:建表时把需要索引的列定义为非空(not null)

3、使用函数

如果没有使用基于函数的索引,那么where子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。下面的查询就不会使用索引:

select * from staff where trunc(birthdate) = '01-MAY-82';

但是把函数应用在条件上,索引是可以生效的,把上面的语句改成下面的语句,就可以通过索引进行查找。

select * from staff where birthdate < (to_date('01-MAY-82') + 0.9999);

4、比较不匹配的数据类型

比较不匹配的数据类型也是难于发现的性能问题之一。

下面的例子中,dept_id是一个varchar2型的字段,在这个字段上有索引,但是下面的语句会执行全表扫描。

select * from dept where dept_id = 900198;

这是因为oracle会自动把where子句转换成to_number(dept_id)=900198,就是3所说的情况,这样就限制了索引的使用。

把SQL语句改为如下形式就可以使用索引

select * from dept where dept_id = '900198';

恩,这里还有要注意的:

比方说有一个文章表,我们要实现某个类别下按时间倒序列表显示功能:

SELECT * FROM articles WHERE category_id = ... ORDER BY created DESC LIMIT ...

这样的查询很常见,基本上不管什么应用里都能找出一大把类似的SQL来,学院派的读者看到上面的SQL,可能会说SELECT *不好,应该仅仅查询需要的字段,那我们就索性彻底点,把SQL改成如下的形式:

SELECT id FROM articles WHERE category_id = ... ORDER BY created DESC LIMIT ...

我们假设这里的id是主键,至于文章的具体内容,可以都保存到memcached之类的键值类型的缓存里,如此一来,学院派的读者们应该挑不出什么毛病来了,下面我们就按这条SQL来考虑如何建立索引:

不考虑数据分布之类的特殊情况,任何一个合格的WEB开发人员都知道类似这样的SQL,应该建立一个”category_id, created“复合索引,但这是最佳答案不?不见得,现在是回头看看标题的时候了:MySQL里建立索引应该考虑数据库引擎的类型!

如果我们的数据库引擎是InnoDB,那么建立”category_id, created“复合索引是最佳答案。让我们看看InnoDB的索引结构,在InnoDB里,索引结构有一个特殊的地方:非主键索引在其BTree的叶节点上会额外保存对应主键的值,这样做一个最直接的好处就是Covering Index,不用再到数据文件里去取id的值,可以直接在索引里得到它。

如果我们的数据库引擎是MyISAM,那么建立"category_id, created"复合索引就不是最佳答案。因为MyISAM的索引结构里,非主键索引并没有额外保存对应主键的值,此时如果想利用上Covering Index,应该建立"category_id, created, id"复合索引。

唠完了,应该明白我的意思了吧。希望以后大家在考虑索引的时候能思考的更全面一点,实际应用中还有很多类似的问题,比如说多数人在建立索引的时候不从Cardinality(SHOW INDEX FROM ...能看到此参数)的角度看是否合适的问题,Cardinality表示唯一值的个数,一般来说,如果唯一值个数在总行数中所占比例小于20%的话,则可以认为Cardinality太小,此时索引除了拖慢insert/update/delete的速度之外,不会对select产生太大作用;还有一个细节是建立索引的时候未考虑字符集的影响,比如说username字段,如果仅仅允许英文,下划线之类的符号,那么就不要用gbk,utf-8之类的字符集,而应该使用latin1或者ascii这种简单的字符集,索引文件会小很多,速度自然就会快很多。这些细节问题需要读者自己多注意,我就不多说了。

本文地址:http://www.45fan.com/a/question/41066.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573731.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

h5页面不可 移动_H5营销|为什么H5适合于微信营销

随着互联网技术的不断发展&#xff0c;更新在移动互联网时代&#xff0c;网络营销也开始越来越新颖化&#xff0c;而微信H5就是其中的佼佼者。它的出现满足了用户视觉上的审美要求&#xff0c;并且可以使营销方式变得更加的美观整洁&#xff0c;那么这里就有一个问题。为什么微…

input框

input: 输入时与输入框有点距离 padding-left: 5px; 点击时没有浅蓝色的框&#xff1a; outline: none; 设置输入框背景颜色&#xff1a;background: seagreen; 提示语&#xff1a; placeholder"请输入搜索内容" 放在HTML 输入框有图像&#xff1a; background-image…

python3 image_python3 ImageTk 安装方法

标签&#xff1a;使用命令&#xff1a;$ sudo yum search PIL | grep python3可显示得知&#xff1a;python3-dogpile-cache.noarch : A caching front-end based on the Dogpile lock.python3-dogpile-core.noarch : A ‘dogpile‘ lock, typically used as a component ofpyt…

亚太地区数学建模优秀论文_数学建模美赛强势来袭!

01美赛&#xff0c;即美国大学生数学建模竞赛(MCM/ICM)又要来啦&#xff01;赛题内容涉及经济、管理、环境、资源、生态、医学、安全、未来科技等众多领域。竞赛要求三人(本科生)为一组&#xff0c;在四天时间内&#xff0c;就指定的问题完成从建立模型、求解、验证到论文撰写的…

《软件调试》读书笔记:第13章 硬错误和蓝屏

会话管理器进程SMSS.exe是系统启动后的第一个用户态进程&#xff0c;负责启动和监护windows子系统进程&#xff1a;CSRSS.exe和登陆管理进程&#xff1a;WinLogonSMSS.exe从注册表中查询子系统exe文件的位置&#xff0c;并且启动它 CSRSS是windows子系统进程&#xff0c;自NT4以…

java selenium教程_Selenium3 Java自动化测试完整教程

本课程为一个完整的selenium自动化测试实战课程&#xff0c;采用当前**的版本3。学完后可以独立构建起企业级/项目级的自动化测试&#xff0c;从搭建环境、编写脚本、使用框架组织运行脚本与输出报告、及与持续集成工具Jenkins结合达到构建后即测试或指定晚上运行等方式&#x…

信息安全技术网络安全等级保护定级指南_行业标准 |报业网络安全等级保护定级参考指南V2.0发布,明确保护对象、定级要求...

近期&#xff0c;中国新闻技术工作者联合会正式发布《报业网络安全等级保护定级参考指南V2.0》。该指南由中国新闻技术工作者联合会组织网络安全领域的专家、报业技术专家以及业务专家经过多次调研、学习、探讨后&#xff0c;在原《报业网络安全等级保护定级参考指南V1.0》的基…

nRF51822 硬件复位引脚

nRF51822 有一个硬件复位引脚和Debug 口SWDIO是共用的&#xff0c;名字叫做nReset. 实现硬件复位是怎样子的&#xff1a; 1、这个引脚引出来&#xff0c; 2、给这个引脚低电平&#xff0c; 3、从低电平拉到高电平&#xff0c;即复位。 其实就是给这个引脚一个低电平脉冲。 转载…

java点赞功能实现_JavaWeb中点赞功能的实现及完整实例

实现原理1、功能描述&#xff1a;一个用户对同一文章只能点赞一次&#xff0c;第二次就是取消赞2、建立一个点赞表great&#xff0c;字段有文章ID(aid)&#xff0c;点赞用户ID(uid)3、当有用户进行点赞行为时&#xff0c;使用aid和uid搜索点赞表。若有该记录&#xff0c;则表示…

数学作图工具_科研论文作图系列-从PPT到AI (一)

导语&#xff1a;之前的推送中&#xff0c;小编给大家介绍过几款科研作图软件&#xff0c;包括统计分析软件Origin和Prism&#xff0c;图像处理软件ImageJ等等。从本期开始&#xff0c;小编将和大家一起继续学习科研论文作图。重点介绍图像的处理和排版&#xff0c;用到的工具主…

传送图片程序

前言&#xff1a;以C#为程序设计基础&#xff0c;传输大图片&#xff0c;并现实。在过程中&#xff0c;采用套接字&#xff0c;单线程同步机制为例子。需要深化&#xff0c;可以采用异步或者多线程的机制&#xff0c;保障能够顺利执行。具体代码可以到微云下载【链接&#xff1…

java中no1_【Java】-- 网络编程のNo.1

在现有的网络中&#xff0c;网络通讯的方式主要有两种&#xff1a;TCP(传输控制协议)方式UDP(用户数据报协议)方式在网络通讯中&#xff0c;TCP方式就类似于拨打电话&#xff0c;使用该种方式进行网络通讯时&#xff0c;需要建立专门的虚拟连接&#xff0c;然后进行可靠的数据传…

优启通怎么重装系统win10_重装系统失败?小编教你安全给神舟战神GX9 Pro重装win10系统方法...

神舟战神GX9 Pro 上市于2016年1月&#xff0c;虽然现在已经停产&#xff0c;但是还是有不少用户依旧十分喜爱这款笔记本。这款笔记本的性能完全对得起它的售价&#xff0c;很多用户都反馈其比外星人电脑要好。对于爱玩游戏的用户而言&#xff0c;对它17.3英寸的显示屏简直欲罢不…

.NET小细节

1、equals()和运算符的区别 C#中有两种不同的相等&#xff1a;引用相等和值相等。值相等是两个对象包含相同的值&#xff1b;引用相等是两个对象引用的是同一个对象。 “”操作符比较的是两个变量的值是否相等&#xff0c;或两个引用是不是指向同一个内存地址&#xff08;类似比…

java exception用法_Java基础回顾_Exception异常使用详解

package 内部类异常包装器;public class 异常 {/*** 1.异常:* 有Error和Exception两个基本子类* 2.Error:* Error表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。* 3.Exception:* 表示一种设计或实现问题。也就是说&…

获得代理ippython_Python搭建代理IP池实现获取IP的方法

使用爬虫时&#xff0c;大部分网站都有一定的反爬措施&#xff0c;有些网站会限制每个 IP 的访问速度或访问次数&#xff0c;超出了它的限制你的 IP 就会被封掉。对于访问速度的处理比较简单&#xff0c;只要间隔一段时间爬取一次就行了&#xff0c;避免频繁访问&#xff1b;而…

20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结...

week 8 实验&#xff1a;理解进程调度时机跟踪分析进程调度与进程切换的过程 1.环境搭建&#xff1a; rm menu -rf git clone https://github.com/megnning/menu.git cd menu ls make rootfs qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S …

java jni技术_JNI技术简介

JNI(Java Native Interface)提供一种Java字节码调用C/C的解决方案&#xff0c;JNI描述的是一种技术。NDK(Native Development Kit)Android NDK 是一组允许您将 C 或 C(“原生代码”)嵌入到 Android 应用中的工具&#xff0c;NDK描述的是工具集。 能够在 Android 应用中使用原生…

python 读取mysql大量数据处理_python使用多线程快速把大量mysql数据导入elasticsearch...

使用python多线程&#xff0c;运行时自定义线程数&#xff0c;自动计算每个线程处理的数据量&#xff0c;连接mysql读取数据&#xff0c;处理成需要的字段入到elasticsearch。运行效果图&#xff1a;10个线程 运行会在这里实时刷新&#xff0c;方便查看每个线程处理到的id数&am…

java web redis_java web redis使用(二)

上篇中已经安装好redis&#xff0c;然后下面就说怎么在java web中用客户端来使用regis使用jedis java客户端一&#xff1a;一个简单的示例代码:public static void main(String[] args) {Jedis jedis new Jedis( "147.151.240.234" , 6379 );jedis.set("foo&…