mysql索引优化

1.mysql 的存储形式是b+tree 。

2.使用索引时机

1.哪些情况需要创建索引

1).主键自动建立唯一索引

2).频繁作为查询查询条件的字段应该创建索引

3).查询中与其它表关联的字段,外键关系建立索引

4).频繁更新的字段不适合创建索引

5).where条件里用不到的字段不创建索引

6).单键/组合索引的选择问题(在高并发下倾向创建组合索引)

7).查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度

8).查询中统计或者分组字段

2.哪些情况不要创建索引

1).表记录太少

2).经常增删改的表(因为不仅要保存数据,还要保存一下索引文件)

3).数据重复且分布平均的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。

注意:如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。


二张表

性能优化:left join是由左边决定的,左边一定都有,所以右边是我们的关键点,建立索引要建右边边。当然如果索引在左边,可以用右连接。

1

2

select * from atable 

left join btable  on atable.aid=btable.bid;  // 最好在bid上建索引

结论:

尽可能减少Join语句中的NestedLoop的循环次数:“永远用小结果集驱动大的结果集”

避免索引失效

2.最佳左前缀法则:如果索引了多列,要尊守最左前缀法则,指的是查询从索引的最左前列开始并且不跳过索引中的列。

3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。

4.存储引擎不能使用索引中范围条件右边的列。

如这样的sql: select * from user where username='123' and age>20 and phone='1390012345',其中username, age, phone都有索引,只有username和age会生效,phone的索引没有用到。

5.尽量使用覆盖索引(只访问索引的查询(索引列和查询列致)),如select age from user减少select *

6.mysql在使用不等于(!= 或者 <>)的时候无法使用索引会导致全表扫描。

7.is null, is not null 也无法使用索引。

8.like 以通配符开头(‘%abc..’)mysql索引失效会变成全表扫描的操作。

所以最好用右边like 'abc%'。如果两边都要用,可以用select age from user where username like '%abc%',其中age是索引列

假如index(a,b,c), where a=3 and b like 'abc%' and c=4,a能用,b能用,c不能用

9.字符串不加单引号索引失效

10.少用or,用它来连接时会索引失效

11.尽量避免子查询,而用join

一般性建议

对于单键索引,尽量选择针对当前query过滤性更好的索引

在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好

在选择组合索引的时候,尽量选择可以能够包含当前query中的where子句中更多字段的索引

尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的。

left/right join注意

1).on与 where的执行顺序

ON 条件(“A LEFT JOIN B ON 条件表达式”中的ON)用来决定如何从 B 表中检索数据行。如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 NULL 的数据,在匹配阶段 WHERE 子句的条件都不会被使用。仅在匹配阶段完成以后,WHERE 子句条件才会被使用。它将从匹配阶段产生的数据中检索过滤。

所以我们要注意:在使用Left (right) join的时候,一定要在先给出尽可能多的匹配满足条件,减少Where的执行。如:

2).注意ON 子句和 WHERE 子句的不同

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

mysql> SELECT * FROM product LEFT JOIN product_details

      ON (product.id = product_details.id)

      AND product_details.id=2;

+----+--------+------+--------+-------+

| id | amount | id  | weight | exist |

+----+--------+------+--------+-------+

|  1 |    100 | NULL |  NULL |  NULL |

|  2 |    200 |    2 |    22 |    0 |

|  3 |    300 | NULL |  NULL |  NULL |

|  4 |    400 | NULL |  NULL |  NULL |

+----+--------+------+--------+-------+

4 rows in set (0.00 sec)

mysql> SELECT * FROM product LEFT JOIN product_details

      ON (product.id = product_details.id)

      WHERE product_details.id=2;

+----+--------+----+--------+-------+

| id | amount | id | weight | exist |

+----+--------+----+--------+-------+

|  2 |    200 |  2 |    22 |    0 |

+----+--------+----+--------+-------+

1 row in set (0.01 sec)

  从上可知,第一条查询使用 ON 条件决定了从 LEFT JOIN的 product_details表中检索符合的所有数据行。第二条查询做了简单的LEFT JOIN,然后使用 WHERE 子句从 LEFT JOIN的数据中过滤掉不符合条件的数据行。


1.永远小表驱动大表

在java程序里,两个for循环,循环次数不管谁先谁后都是两者次数相乘。

但在mysql的语句中,一定要小表驱动大表,因为小表跟Mysql连接和释放数量少

如in与exists

1

2

3

4

5

6

7

8

9

10

11

12

13

select * from A where id in (select id form B)

等价于

for select id from B

for select * from A where A.id=B.id

结论:当B表的数据集必须小于A表的数据集时,用in优于exists。

select * from A where exists (select 1 from B where B.id=A.id) // 这里的1用任何常量都行

等价于

for select * from A

for select * from B where B.id=A.id

结论:当A表的数据集必须小于B表的数据集时,用in索引优化分析 | liucw's blog链接1优于。

注意:A表与B表的ID字段应建立索引

exists通用语法select ... from table where exists (subquery)

该语法可以理解为:将主查询的数据,放到子查询中做条件验证,根据验证结果(true或false)来决定主查询的数据结果是否得以保留。

提示:

1).exists(subquery)只返回true或false, 因此子查询中select *也可以是select 1或select 'X', 官方说法是实际执行会忽略select 清单,因此没有区别。

2).exists 子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比,如果担忧效率问题,可进行实际检验。

3).exists 子查询往往也可以用条件表达式、其他子查询或者JOIN来替代,何种最优需要具体问题具体分析。


链接1

链接2

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

推荐阅读更多精彩内容