四时宝库

程序员的知识宝库

MySQL 联合索引(mysql 联合索引 顺序)

命名规则:表名_字段名

1、需要加索引的字段, 要在where条件中

2、数据量少的字段不需要加索引(推荐2000条为界)

3、如果where条件中是OR关系, 加索引不起作用

4、符合最左原则

联合索引又叫复合索引。对于复合索引: Mysql从左到右的使用索引中的字段, 一个查询可以只使用索引中的一部份, 但只能是最左侧部分。

例如: 索引是key index (a,b,c), 可以支持 a | a,b | a,b,c 3种组合进行查找, 但不支持 b,c 进行查找, 当最左侧字段是常量引用时, 索引就十分有效。

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

利用索引中的附加列, 您可以缩小搜索的范围, 但使用一个具有两列的复合索引, 不同于使用两个单独的索引。

复合索引的结构与电话簿类似, 人名由姓和名构成, 电话簿首先按姓氏对进行排序, 然后按名字对有相同姓氏的人进行排序。

如果您知道姓, 电话簿将非常有用; 如果您知道姓和名, 电话簿则更为有用, 但如果您只知道名不姓, 电话簿将没有用处。

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

当一个表有多条索引可走时, Mysql根据查询语句的成本来选择走哪条索引, 联合索引的话, 它往往计算的是第一个字段(最左边那个), 这样往往会走错索引. 如:

索引Index_1(create_Time, Category_id), Index_2(Category_id)

如果每天的数据都特别多, 而且有很多category, 但具体每个category的记录不会很多.

当查询SQL条件为 select ... where create_time ... and category_id= ... 时, 很可能不走索引Index_1, 而走索引Index_2, 导致查询比较慢.

解决办法是将索引字段的顺序调换一下Index_1(category_id, create_Time)。

什么情况下应不建或少建索引

1 表记录太少, 如果一个表只有5条记录, 采用索引去访问记录的话, 那首先需访问索引表, 再通过索引表访问数据表, 一般索引表与数据表不在同一个数据块, 这种情况下至少要往返读取数据块两次。

而不用索引的情况下, 会将所有的数据一次读出, 处理速度显然会比用索引快。

2 经常插入、删除、修改的表

3 数据重复且分布平均的表字段

假如一个表有10万行记录, 有一个字段A只有T和F两种值, 且每个值的分布概率大约为50%, 那么对这种表A字段建索引一般不会提高数据库的查询速度。

4 经常和主字段一块查询但主字段索引值比较多的表字段

对于复合索引: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 * from test where a=10 and b>50

差: select * from test where c = 50

优: select * from test where order by a

差: select * from test where order by b

差: select * from test where order by c

优: select * from test where a=10 order by a

优: select * from test where a=10 order by b

差: select * from test where a=10 order by c

优: select * from test where a>10 order by a

差: select * from test where a>10 order by b

差: select * from test where a>10 order by c

优: select * from test where a=10 and b=10 order by a

优: select * from test where a=10 and b=10 order by b

优: select * from test where a=10 and b=10 order by c

优: select * from test where a=10 and b=10 order by a

优: select * from test where a=10 and b>10 order by b

差: select * from test where a=10 and b>10 order by c

复合索引对排序的优化:

复合索引只对和索引中排序相同或相反的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. 增加了插入和删除的操作时间。一个表拥有的索引越多, 插入和删除的速度越慢。如: 要求快速录入的系统不宜建过多索引。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接