高性能mysql(5)-创建高性能索引

1.高性能索引策略

1.1独立的列

“独立的列”是指索引不能是表达式的一部分也不能使函数的参数

select name from actor where id+1=5;

这种情况索引失效。我们应该简化where条件始终将单独的列放在比较符号的一侧。

1.2前缀索引和索引选择性

当索引是很长的字符列的时候,会让索引变得大且慢,除了模拟哈希索引的方法,通常选择索引的部分开始字符,从而提高索引效率。但是这样会降低索引的选择性,索引的选择性是指,不重复的索引值(也称为基数,cardinality)和数据表总记录的比值,基数越大查询效率越高,唯一索引的选择性是1,这是最好的选择性,性能也是最好的。
前缀索引的选择应当保证较高的选择性同时又不能太长。

  • 计算列的完整性
select count(distinct rowname)/count(*) from table;
  • 统计不同长度前缀的选择性
select count(distinct left(rowname,num))/count(*) as selnum,
... 
from table;
  • 创建前缀索引
alter table tablename add key (rowname(num));

在mysql中不能用前缀索引做order by 和 group by,也没有办法做覆盖扫描。

1.3 多列索引

当where有多个and,or条件的时候,应当创建多列索引而不是单列索引,应当将or改写为union更加合适,当explain中的extra 出现using union证明使用了索引合并,说明索引建立的很糟糕。

1.4选择合适的索引列顺序

当不排序或者分组的时候,将选择性最高的列放在前面通常的结果可能是不错的。

1.4聚簇索引

在InnoDB引擎中表数据没有什么聚集,应当尽量的使用自增主键(单调递增的聚簇主键)按主键顺序去插入数据,避免大量的随机IO。

1.5覆盖索引

如果一个索引包含所有需要查询的字段值,我们就称之为覆盖索引。只有B树索引能做覆盖索引,因为覆盖索引必须存储索引列的值。并且不是所有的存储引擎都支持覆盖索引,例如menory就不支持覆盖索引。使用覆盖索引会带来较大的性能提升,因为索引的条目要远远小于数据行大小,可以转化随机IO为顺序IO,减少IO的次数。在InnoDB引擎中二级索引包含了主键值,所以即使索引字段不包含主键,依然能对主键值做覆盖索引。

CREATE TABLE products (
 id int(11) NOT NULL AUTO_INCREMENT ,
 actor  varchar(30)   NOT NULL ,
 sur_name varchar(30) DEFAULT NULL ,
 name  varchar(30)   NULL DEFAULT NULL ,
 title  varchar(30)  S NOT NULL ,
 PRIMARY KEY (id),
 INDEX key_1 (actor, title) USING BTREE 
);

查询

explain select * from products where actor='tom' and title='%asd%';
图片.png

此时代表通过索引访问表,看是否需要全表扫描,这时索引的信息推迟使用,必要时读全表。因为虽然索引覆盖了where中的字段,但是没有覆盖整个查询的字段。所以还是会读表,而且"%%"导致只能使用第一列索引。

优化:

explain select id from products where actor='tom' and title like '%asd%';

图片.png

虽然id没有在where条件的索引范围之内但是依然使用了覆盖索引。
正如上面所说在InnoDB引擎中二级索引包含了主键值,所以即使索引字段不包含主键,依然能对主键值做覆盖索引。

EXPLAIN SELECT  * FROM products
JOIN (
    SELECT
        id
    FROM
        products
    WHERE
        actor = 'tom'
    AND title LIKE '%asd%'
) AS t1 ON (t1.id = products.id);

这里采用的方式是延迟关联 。

图片.png

这里虽然外层查询的type是ALL但是如果内层查询的结果集足够小的话。性能会有很大的提升(内层查询前提是结果集足够小),但是如果本身的数据量就不大的话,使用延迟关联反而会因为子查询而带来额外的开销,性能反而下降。

1.6使用索引扫描做排序

当explain的type列值为index则说明使用索引扫描做排序。
限制:

  • 只有当索引列顺序和order by子句顺序完全一致,并且所有列的排序方向一致时,才能使用索引对结果做排序。
  • 如果查询要关联多张表,只有当order by子句的字段全部为第一张表时才能用索引做排序。
  • order by 子句也需要满足最左前缀要求,否则不能做排序。
  • 范围查询可能会导致索引排序失效
    当索引为覆盖索引时按索引排序的效率是高的。否则性能将会下降。

总结

  1. 通常情况下我们使用我们使用选择性高的字段作为索引的第一列,
    但是有时候某一个字段的选择性不高但是却经常出现在where子句中,例如sex,这时我们可以选用sex做为索引字段的第一列,在不需要性别的时候通过sex in ('w','m'),过滤这个索引。但是要注意的是in()的列表不能太长。
  2. 对于范围查询应当避免多个范围条件,而使用IN(),但是滥用IN()会导致优化器组合成指数形式增加,范围条件应当建立在索引的最后一列。
  3. 在同时使用order by 和 limit 查询的时候即使使用了索引在翻页到最后的面的时候,需要花费大量的时间丢弃数据,是一个严重的问题。
select <cols> from profiles where sex='m' order by rating limit 10000,10;

优化此类索引应当使用延迟关联

 select <cols> from profiles 
 join(
   select <primary key> from profiles 
   where sex='m' order by rating limit 10000,10;

 ) as t1 on(t1.<primary key>=profiles.<primary key>); 
  1. 减少索引和数据碎片
optimize table

对于不支持optimize table的存储引擎可以先改为InnoDB执行后,再修改回去。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容