5.4索引学习案例《创建高性能的索引》

设计一个在线约会网站,用户信息表:国家,地区,城市,性别,眼睛颜色等等。支持各种组合来搜索用户:最后在线时间,评分等进行排序的限制。

索引来排序,还是先检索数据再排序?

索引排序:严格限制索引和查询的设计。索引做评分排序,则WHERE 条件中的 age BETWEEN 18 AND 25 就无法使用索引。

1、支持多种过滤条件

(1)(country,sex)作为前缀:country、sex选择性很低,很多查询用到

和不应该在选择性低的列上创建索引是矛盾,因为:

a、sex使用的太频繁。

b、加了这列没坏处,即没用sex,增加and sex in ('m','f'),不会过滤任何行,能够匹配索引最左前缀,但不要让in()列表太长。

(2)优化索引和优化查询要平衡:(sex,country,age),(sex,country,region,age),(sex,country,region,city,age),重用索引,in()技巧很重要

WHERE eye_color in('brown','blue','hazel')

AND hair_colr in ('black','red','blonde','borwn') 

AND sex in ('f','m') 

优化器会转成3*4*2=24种组合,查询优化很多时间,并消耗大量的内存

(3)范围查询较多的列放在后面:例age列

2、避免多个范围查询

explain的输出很难区分范围查询(<,>,between)和列表值查询in(),因为explain中的type都是range,访问效率不同,前者索引不能用了,后者却可以。

last_online列,查询显示在过去几周上线过的用户:

  WHERE eye_color in('brown','blue','hazel')

      AND hair_colr in ('black','red','blonde','borwn')

      AND sex in ('f','m')

      AND last_online > DATE_SUB(NOW(),INTERVAL 7 DAY) 

      AND age between 18 and 25

last_onlin、age列索引,无法同时使用

解决办法:active列,每次登陆设为1,连续7天未登陆设为0

3、优化排序

SELECCT <cols> FROM  profiles WHERE sex='M' ORDER BY rating limit 10;   //同时使用order by 和limit ,如果没有索引的话,会很慢

SELECCT <cols> FROM  profiles WHERE sex='M' ORDER BY rating limit 100000,10;//即使有索引,翻页到比较靠后时,查询也慢。

解决办法:(1)限制用户能够翻页的数量,实际上这对用户的体验不大,因为用户很少真正在乎搜索过的低10000页。

(2)延迟关联,通过使用腹杆索引查询返回需要的主键,在根据这些主键关联原表格所需要的行。这可以减少MySQL扫描那些需要丢弃的行数。下面这个查询显示了如何高效的使用(sex,rating)索引进行排序和分页

 SELECT <cols> FROM profiles INNER JOIN (

               SELECT <primary key cols> FROM profiles

               WHERE x.sex = 'M' ORDER BY rating 10000,10

    ) AS X using (<primary key cols>);

表里有100万记录,如图:

select * from emp3 inner join ( select id from emp3 where num1=1 order by job_num limit 100000,10) as x using(id);

20W的数据:

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容