你做了一个明智的选择
-
理解索引对开发和dba来说都是极其重要
-
差劲的索引对产品问题负相当大的一部分责任
-
索引不是多么高深的问题
MySQL 索引一览表
-
理解索引
-
为你的应用创建最佳索引
-
拥抱MySQL的限制
简述索引
索引有什么用
你可能听说过的索引类型
-
BTREE索引 – mysql中主要的索引类型
-
RTREE索引 – 只有MyISAM支持, 用于GIS
-
HASH 索引 – MEMORY, NDB 支持
-
BITMAP 索引 – MySQL 不支持
-
FULLTEXT 索引 – MyISAM, Innodb(MySQL 5.6以上支持)
类BTREE索引家族
-
有很多不同的实现
-
在可加速的操作中共享相同的属性
-
内存相比硬盘使生活变得美好
-
B+树通常用于硬盘存储
B+Tree 示例
MyISAM、Innodb索引对比
-
MyISAM
-
数据指针指向数据文件中的物理位置
-
所有索引都是一样的(指向物理位置))
-
Innodb
BTREE索引能用于什么操作 ?
字符索引
-
这(和数值)没什么区别… 真的
-
collation是为字符串定义的排序规则
-
如: “AAAA” < “AAAB”
-
前缀LIKE 查询是一种特殊的范围查询
-
LIKE “ABC%” 的意思是:
-
“ABC[最小值]”
-
LIKE “%ABC” 无法使用索引查询
联合索引
索引的开销
索引成本的影响
-
长主键索引(Innodb)
– 使所有相应的二级索引 变得更长、更慢
-
“随机”主键索引(Innodb)
– 插入导致大量的页面分割
-
越长的索引通常越慢
-
Index with insertion in random order
– SHA1(‘password’)
-
低区分度的索引是低劣的
– 在性别字段建的索引
-
相关索引是不太昂贵的
– insert_time与自增id是相关的
Innodb表的索引
-
数据按主键聚集
-
或者 “打包” 单个 BIGINT(字段)
-
主键隐式地附加到所有索引中
-
覆盖索引,有利于排序
MySQL是如何使用索引的
-
查询
-
排序
-
避免读取数据(只读取索引)
-
其他专门的优化
使用索引进行查询
复合索引比较复杂
-
Index (A,B,C) - 字段顺序问题
-
下列情形将会使用索引进行查询(全条件)
-
下列条件将不会使用索引
-
以下情形使用索引的一部分
MySQL优化器的第一法则
所用索引进行排序
高效排序的联合索引
-
变得更加受限!
-
KEY(A,B)
-
以下情形将会使用索引进行排序
-
ORDER BY A - 对索引首字段进行排序
-
A=5 ORDER BY B - 对第一个字段进行点查询,对第二个字段进行排序
-
ORDER BY A DESC, B DESC - 对两个字段进行相同的顺序进行排序
-
A>5 ORDER BY A - 对首字段进行范围查询,并对首字段进行排序
-
以下情形将不使用索引进行排序
-
ORDER BY B - 对第二个字段进行排序(未使用首字段)
-
A>5 ORDER BY B – 对首字段进行范围查询,对第二个字段进行排序
-
A IN(1,2) ORDER BY B - 对首字段进行IN查询,对第二个字段进行排序
-
ORDER BY A ASC, B DESC - 对两个字段进行不同顺序的排序
MySQL使用索引排序的规则
避免读取数据(只读取索引)
Min/Max的优化
联表查询中索引的使用
-
MySQL 使用 “嵌套循环(Nested Loops)”进行联表查询
-
SELECT * FROM POSTS,COMMENTS WHERE
AUTHOR=“Peter” AND COMMENTS.POST_ID=POSTS.ID
-
扫描表POSTS查询所有复合条件的 posts
-
循环posts 在表COMMENTS 中查找 每个post的所有comments
-
使每个关联的表(关联字段)都使用上索引显得非常的重要
-
索引只有在被查询的字段上是必要的
– POSTS.ID字段的索引再本次查询中是用不上的
-
重新设计不能很好的所有索引的联合查询吧
使用多索引
前缀索引
选择前缀长度
mysql> select count(distinct(title)) total,count(distinct(left(title,10))) p10,count(distinct(left(title,20))) p20 from title;
total
|
p10
|
p20
|
998335
|
624949
|
960894
|
1 row in set (44.19 sec)
使用最多的Title
mysql> select count(*) cnt, title tl from title group by tl order by cnt desc limit 3;
cnt
|
tl
|
136
|
The Wedding
|
129
|
Lost and Found
|
112
|
Horror Marathon
|
3 rows in set (27.49 sec)
使用最多的Title 前缀
mysql> select count(*) cnt, left(title,20) tl from title group by tl order by cnt desc limit 3;
cnt
|
tl
|
184
|
Wetten, dass..? aus
|
136
|
The Wedding
|
129
|
Lost and Found
|
3 rows in set (33.23 sec)
MySQL如何选择使用哪个索引的?
更多关于索引的选择
使用EXPLAIN
id
|
select_type
|
table
|
type
|
possible_keys
|
key
|
key_len
|
ref
|
rows
|
Extra
|
1
|
SIMPLE
|
title
|
range
|
NULL
|
production_year
|
5
|
NULL
|
201
|
Using index for group-by
|
1 row in set (0.01 sec)
MySQL Explain 101
-
“type” 从好到差排序如下:
– system,const,eq_ref,ref,range,index,ALL
-
注意 “rows” – 更大的数值意味着更慢的查询
-
检查 “key_len” – 显示索引的哪些部分真实使用到了
-
留意"Extra"
索引策略
索引策略示例
Trick #1: 枚举范围
-
KEY (A,B)
-
SELECT * FROM TBL WHERE A BETWEEN 2
AND 4 AND B=5
-
SELECT * FROM TBL WHERE A IN (2,3,4) AND
B=5
Trick #2: 添加一个假的条件
-
KEY (GENDER,CITY)
-
SELECT * FROM PEOPLE WHERE CITY=“NEW
YORK”
-
SELECT * FROM PEOPLE WHERE GENDER IN
(“M”,”F”) AND CITY=“NEW YORK”
Trick #3: 虚实Filesort
-
KEY(A,B)
-
SELECT * FROM TBL WHERE A IN (1,2) ORDER BY
B LIMIT 5;
-
(SELECT
FROM TBL WHERE A=1 ORDER BY B LIMIT 5) UNION ALL (SELECT
FROM TBL WHERE A=2 ORDER BY B LIMIT 5) ORDER BY B LIMIT 5;