MYSQL-索引&SQL优化-IM

索引选择策略:

索引的选择性(Selectivity),是指不重复的索引值(也叫基数,Cardinality)与表记录数(#T)的比值:取值范围为(0, 1],选择性越高的索引价值越大[即索引列值越离散索引价值越大,如:性别就男女2个值,在性别列上建立索引无法达到快速定位缩小行范围目的]

SELECT count(DISTINCT(first_name)) / count(*)AS Selectivity FROM employees;

SELECT count(DISTINCT(concat(first_name,last_name)))/count(*)AS Selectivity FROM employees;

SELECT count(DISTINCT(concat(first_name,left(last_name,4))))/count(*) AS Selectivity FROM employees;

选择索引字段原则:

数据类型: 选范围小的 & 选类型简单的 & 尽量not null

(mysql难以优化包含null字段查询,有必要时设置一个默认值)

字段值: 值域尽量离散,区分度高


索引优化策略:

1. 【强制】业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。 说明:不要以为唯一索引影响了insert速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

2.【强制】 超过三个表禁止join(消耗较多内存,产生临时表)。需要join的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。 说明:即使双表join也要注意表索引、SQL性能。

3.【强制】在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为20的索引,区分度会高达90%以上,可以使用count(distinct left(列名, 索引长度))/count(*)的区分度来确定。

4.【强制】页面搜索严禁左模糊或者全模糊(造成索引失效),如果需要请走搜索引擎来解决。 说明:索引文件具有B-Tree的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。右模糊能命中索引

5.【推荐】如果有order by的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。 正例:where a=? and b=? order by c; 索引:a_b_c 反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引a_b无法排序。

6.【推荐】利用覆盖索引来进行查询操作,避免回表。 说明:如果一本书需要知道第11章是什么标题,会翻开第11章对应的那一页吗?目录浏览一下就好,这个目录就是起到覆盖索引的作用。 正例:能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种效果,用explain的结果,extra列会出现:using index。

7.【推荐】利用延迟关联或者子查询优化超多分页场景。[优化深度分页问题]

说明:MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。 正例:先快速定位需要获取的id段,然后再关联:

正例:先快速定位需要获取的id段,然后再关联:

SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

8.【推荐】 SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好。 说明: 1)consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。 2)ref 指的是使用普通的索引(normal index)。 3)range 对索引进行范围检索。 反例:explain表的结果,type=index,索引物理文件全扫描,速度非常慢,这个index级别比较range还低,与全表扫描是小巫见大巫。

9.【推荐】建组合索引的时候,区分度最高的在最左边。 正例:如果where a=? and b=? ,a列的几乎接近于唯一值,那么只需要单建idx_a索引即可。 说明:存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如:where a>? and b=? 那么即使a的区分度更高,也必须把b放在索引的最前列。

10.【参考】创建索引时避免有如下极端误解: 1)误认为一个查询就需要建一个索引。 2)误认为索引会消耗空间、严重拖慢更新和新增速度。 3)误认为唯一索引一律需要在应用层通过“先查后插”方式解决。

11.表必须有主键建议使用自增id作为主键,建议不要选择字符串作为主键(如:身份证号、UUID),空间占用大&索引效率低。

12.合理创建复合索引(避免冗余)-最左前缀: index(a,b,c) 相当于建立index(a),index(a,b),index(a,b,c)

13.不要索引列上进行数学或函数运算-会导致索引失效

反例: SELECT c2,c3 FROM t WHERE date(c1) = ‘2016-10-15’

14.对字符列使用前缀索引:区分度决定索引长度[count(distinct left(列名, 索引长度))/count(*)的区分度],一般不超过20

15.不使用 左模糊或者全模糊(造成索引失效),右模糊可以命中索引

反例: SELECT c2,c3 FROM t WHERE c4 like ‘%???%’

16.不使用反向查询,如: not in / not like -无法使用索引,全表扫描。

17.避免隐士类型转换,导致索引失效: 类型不匹配导致

select user_id from user_info where user_id = '123'

18.最左前缀,最多利用一个范围条件:2个及以上导致索引失效

正例:

SELECT*FROM employees.titles WHERE emp_no<'10010'and title='Senior Engineer';

反例:

SELECT*FROM employees.titles

WHERE emp_no<'10010'

AND title='Senior Engineer'

AND from_date BETWEEN'1986-01-01'AND'1986-12-31';

19.in 代替or ,in的值不超过1000个。

20.禁用select * ,使用哪些列就查询哪些列。(选择更多列意味占用更多buffer缓冲区,如果超过最大buffer缓存区能容纳size则会进行IO读取建立临时表等操作,速度降低。所以尽量查我们需要的列)无法使用覆盖索引&降低解析成本。

21.能UNION ALL就不要UNION(UNION需要去重,会产生临时表)

22.不要使用外键:高并发场景影响性能。

23.尽量不使用TEXT、BLOB类型,如果使用 拆分大字段和访问频率低的字段,分离冷热数据。

24.分表策略: hash or 日期时间(yyyy-mm-dd格式)

运维好习惯:

1.关闭QUERY CACHE

–绝大多数情况下鸡肋,最好关闭

–QC锁是全局锁,每次更新QC的内存块锁代价高,出现Waiting for query cache lock状态的频率很高

–实例启动前设置query_cache_type = 0 & query_cache_size =0

2.使用独立undo表空间

–避免ibdata1文件存储空间暴涨

–MySQL 5.6开始支持独立表空间

–MySQL 5.7还可以回收已经purge的表空间

–提高file i/o能力,并适当增加purge线程数innodb_purge_threads

–事务及时提交,不要积压。并且默认打开autocommit = 1

3.启用thread pool

–应对突发短连接

–extra port

•没thread pool怎么办

–想办法启用连接池或其他替代方案

–适当调低超时阈值,减少空闲连接

4.几个关键选项

–innodb_buffer_pool_size,约物理内存的50% ~ 70%

–innodb_log_file_size,5.5及以上2G+,5.5以下建议不超512M

–innodb_flush_log_at_trx_commit,0=>最快数据最不安全,1=>最慢最安全,2=>折中

–innodb_max_dirty_pages_pct,25%~50%为宜

–max_connections,突发最大连接数的80%为宜,过大容易导致全部卡死

5.启用辅助监控机制

–干掉超过N秒的SQL

–干掉疑似注入SQL

–干掉长时间不活跃的sleep连接

6.autocommit

–避免某些行锁被长时间持有,影响tps

–更严重时,可能连接数暴涨,导致整个实例挂掉

–采用gui客户端连接时,记得及时关闭连接,或设置超时阈值以及自动提交,否则容易发生行锁等待问题

关于EXPLAIN:

–关键业务SQL上线前,都要EXPLAIN确认其执行计划

–或提前分析slow query log,防患未然

–EXPLAIN中如果有Using temporary、Using filesort、或type=ALL时,尽量想办法进行优化

参见:

http://www.cnblogs.com/hellojesson/p/6001685.html

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

推荐阅读更多精彩内容