网站首页制作公司,网站开发面试都会问什么问题,冠县住房和城乡建设局网站,电商网站开发 参考文献《迅猛定位低效SQL#xff1f;》留了一个尾巴#xff1a;select id,name where name‘shenjian‘select id,name,sexwhere name‘shenjian‘多查询了一个属性#xff0c;为何检索过程完全不同#xff1f;什么是回表查询#xff1f;什么是索引覆盖#xff1f;如何实现索引…《迅猛定位低效SQL》留了一个尾巴select id,name where name‘shenjian‘select id,name,sexwhere name‘shenjian‘多查询了一个属性为何检索过程完全不同什么是回表查询什么是索引覆盖如何实现索引覆盖哪些场景可以利用索引覆盖来优化SQL这些这是今天要分享的内容。画外音本文试验基于MySQL5.6-InnoDB。一、什么是回表查询这先要从InnoDB的索引实现说起InnoDB有两大类索引聚集索引(clustered index)普通索引(secondary index)InnoDB聚集索引和普通索引有什么差异InnoDB聚集索引的叶子节点存储行记录因此 InnoDB必须要有且只有一个聚集索引(1)如果表定义了PK则PK就是聚集索引(2)如果表没有定义PK则第一个not NULL unique列是聚集索引(3)否则InnoDB会创建一个隐藏的row-id作为聚集索引画外音所以PK查询非常快直接定位行记录。InnoDB普通索引的叶子节点存储主键值。画外音注意不是存储行记录头指针MyISAM的索引叶子节点存储记录指针。举个栗子不妨设有表t(id PK, name KEY, sex, flag);画外音id是聚集索引name是普通索引。表中有四条记录1, shenjian, m, A3, zhangsan, m, A5, lisi, m, A9, wangwu, f, B两个B树索引分别如上图(1)id为PK聚集索引叶子节点存储行记录(2)name为KEY普通索引叶子节点存储PK值即id既然从普通索引无法直接定位行记录那普通索引的查询过程是怎么样的呢通常情况下需要扫码两遍索引树。例如select * from t where name‘lisi‘;是如何执行的呢如粉红色路径需要扫码两遍索引树(1)先通过普通索引定位到主键值id5(2)在通过聚集索引定位到行记录这就是所谓的回表查询先定位主键值再定位行记录它的性能较扫一遍索引树更低。二、什么是索引覆盖(Covering index)额楼主并没有在MySQL的官网找到这个概念。画外音治学严谨吧借用一下SQL-Server官网的说法。MySQL官网类似的说法出现在explain查询计划优化章节即explain的输出结果Extra字段为Using index时能够触发索引覆盖。不管是SQL-Server官网还是MySQL官网都表达了只需要在一棵索引树上就能获取SQL所需的所有列数据无需回表速度更快。三、如何实现索引覆盖常见的方法是将被查询的字段建立到联合索引里去。仍是《迅猛定位低效SQL》中的例子create table user (id int primary key,name varchar(20),sex varchar(5),index(name))engineinnodb;第一个SQL语句select id,name from user where name‘shenjian‘;能够命中name索引索引叶子节点存储了主键id通过name的索引树即可获取id和name无需回表符合索引覆盖效率较高。画外音ExtraUsing index。第二个SQL语句select id,name,sexfrom user where name‘shenjian‘;能够命中name索引索引叶子节点存储了主键id但sex字段必须回表查询才能获取到不符合索引覆盖需要再次通过id值扫码聚集索引获取sex字段效率会降低。画外音ExtraUsing index condition。如果把(name)单列索引升级为联合索引(name, sex)就不同了。create table user (id int primary key,name varchar(20),sex varchar(5),index(name, sex))engineinnodb;可以看到select id,name … where name‘shenjian‘;select id,name,sex… where name‘shenjian‘;都能够命中索引覆盖无需回表。画外音ExtraUsing index。四、哪些场景可以利用索引覆盖来优化SQL场景1全表count查询优化原表为user(PK id, name, sex)直接select count(name) from user;不能利用索引覆盖。添加索引alter table user add key(name);就能够利用索引覆盖提效。场景2列查询回表优化select id,name,sex … where name‘shenjian‘;这个例子不再赘述将单列索引(name)升级为联合索引(name, sex)即可避免回表。场景3分页查询select id,name,sex …order byname limit 500,100;将单列索引(name)升级为联合索引(name, sex)也可以避免回表。转载https://mp.weixin.qq.com/s?__bizMjM5ODYxMDA5OQmid2651962609idx1sn46e59691257188d33a91648640bcffa5chksmbd2d092d8a5a803baea59510259b28f0669dbb72b6a5e90a465205e9497e5173d13e3bb51b19mpshare1scene1srcidsharer_sharetime1564396837343sharer_shareid7cd5f6d8b77d171f90b241828891a85fkeyabd60b96b5d1f2e52ca45314fb2c95a67fad7a457fe265562eb51a1c026389d3f28c52359f96e920368ab44a5d08ebcbbe2ded474be2ba70731ed8b5dcc5dd68cc0eceb4989a74fb04e5055c78af8d38ascene1uinMTAwMjA4NTM0Mw%3D%3DdevicetypeWindows7version62060739langzh_CNpass_tickettXA4xc7SZYamLpGZz5B6JwJa1ZRvZ4bRlmzFhXwEKeOfloPLulU0O80gsIQUiONbmysql如何避免回表查询