テーブルとカバーインデックスへ戻ります
正式なトークICP、と私たちの最初の関連ストロークストロークの概念の前に、あなたは、ルックバックは、ICPの理解を助けている、理解したときに知っていないときを知っています
サンプル表のビルド tbl_indexを
表tbl_index(CREATE
C1 INT、
C2 INT、
C3 CHAR(1)、
PRIMARY KEY(C1)、
KEYのidx_c2(C2)を
);
インデックスをカバー
カラム場合と条件がインデックスにある列を選択し、インデックスは、被覆率と呼ばれる呼ばれるこの問い合わせ、完成させることができる。もちろん、組み合わせ指数である(InnoDBは、インデックスが基本的なインデックスのビットの特別なカバーでクラスタ化)は、特に下記の図を参照してください。
上記tbl_indexについては、 SELECT C2 から tbl_index WHERE C2 = 4 ; インデックスクエリをカバーし、私たちはtbl_indexテーブルにインデックスを追加した場合、このSQLは、意味がありません インデックス idx_c2_c3(C2、C3) 、その後、 SELECT C3 から tbl_index WHERE C2 = 4 ; インデックスクエリをカバー散歩は何のカバーインデックスを意味し、再び、その問題を理にかなっていますか?私たちは、見下します
テーブルに戻ります
SQLクエリは、直接インデックスで完了することができない(条件列と列を選択した任意のインデックスのすべてが存在しない)、その後、インデックスレコードからこのクエリを完了するために、完全なデータ・レコードのために必要な時間は、対応を取得しますテーブルにコールバックされたデータレコードの処理を完了し、いくつかの抽象的概念は言うかもしれないが、我々はテーブルに戻って何のMySQLの特定の組み合わせを見て
テーブルへのInnoDBの背中
InnoDBのインデックス構造は、次の手順に類似するクラスタ化インデックステーブルにいくつかの特別な、非クラスタ化インデックス(セカンダリインデックス)バック
InnoDBは、インデックス、一緒に常駐すなわちデータ、インデックス、及びデータクラスタ化され、その後、SQLクエリは、テーブルに戻り、クラスタ化インデックスに直接移動がないような、言っ SELECT * から tbl_index C1 = 10 ; のみからセカンダリインデックスクエリは、クエリを完了するために、テーブルにクラスタ化インデックスを返します際に出発し、完成し二次インデックスは一人ですることはできません
MyISAMテーブルのバック
:言ってあり 、二次インデックス内のMyISAMインデックスがあり 、実際には、それがクラスタ化インデックスの構造であり、セカンダリインデックスはちょうどクラスタ化インデックスがユニーク制約を持つ、基本的に同じです
次の表と同様のMyISAMクラスタ化インデックスと二次インデックス、およびそれらのバック手順
MyISAMテーブルとInnoDBのテーブルの裏にはまだ差がある;テーブルへのMyISAMバックは、それがクラスタ化インデックスである、またはセカンダリインデックスはもちろん可能のテーブルに戻ったかどうか、プロセスのリーフノードに記録されたアドレスデータの完全なレコードを取得するプロセスを指しの
それは、おそらく追加のディスクIOをもたらすことがあるバックのMyISAMやInnoDBのテーブルの裏のテーブルにあるかどうか、それは真剣に、クエリの効率に影響を与える、インデックスをカバーする目的は、効率を改善するために、テーブルにプロセス・バックを回避するために、SQLクエリを完了しようとすることです
どのようにMySQLを確認するためには、カバーするインデックスクエリは、クエリがテーブルに戻って作られていますか?
看 MySQL 的执行计划,如果 Extra 中只有 using index 则说明使用了覆盖索引查询,如果 Extra 中出现了 using indexcondition 或 using index & using where 则说明进行了回表查询
ICP
Index Condition Pushdown,MySQL 5.6 中引入的一种优化策略
那么究竟是将什么从哪 Push Down 到哪,优化了什么?要弄清楚这 4 个问题,我们需要先弄清楚 where 条件的提取与应用,具体可查看:神奇的 SQL 之 WHERE 条件的提取与应用
where 条件会被提取成 3 部分: Index Key,Index Filter,Table Filter ,在 MySQL 5.6 之前,并不区分 Index Filter 与 Table Filter,统统将 Index First Key 与 Index Last Key 范围内的索引记录,回表读取完整记录,然后返回给 MySQL Server 层进行过滤,而在 MySQL 5.6 之后,Index Filter 与 Table Filter 分离,Index Filter 下降到引擎层(InnoDB和MyISAM)的索引层面进行过滤,减少了回表与返回 MySQL Server 层的记录交互开销,提高了 SQL 的执行效率
ICP 优化过程
假设我们有表: tbl_icp
create table tbl_icp (a int primary key, b int, c int, d int, e varchar(50));create index idx_bcd on tbl_icp(b, c, d);insert into tbl_icp values (4,3,1,1,'a');insert into tbl_icp values (1,1,1,2,'d');insert into tbl_icp values (8,8,7,8,'h');insert into tbl_icp values (2,2,1,2,'g');insert into tbl_icp values (5,2,2,5,'e');insert into tbl_icp values (3,3,2,1,'c');insert into tbl_icp values (7,4,0,5,'b');insert into tbl_icp values (6,5,2,4,'f');
若没有使用 ICP,则 SQL 查询类似如下
没有使用 ICP 时,引擎层会将满足 Index Key 范围限制的所有数据记录(示例中一共 6 条)逐条返回给 Server 层,然后由 server 层应用 Index Filter 和 Table Filter (MySQL 5.6 之前不区分 Index Filter 和 Table Filter),最后将满足条件的数据返回给客户端;
若使用 ICP,则 SQL 查询类似如下
使用了 ICP,Server 层会将 Index Filter 下推到引擎层,引擎层在对 Index First Key 与 Index Last Key 范围内的索引项逐条进行过滤的时候,会应用上 Index Filter,对不满足 Index Filter 条件的索引项直接过滤掉,无需回表操作,也无需返回给 Server 层,从而提供执行效率;上图中的索引项: 3 1 1 、 3 2 1 不满足 Index Filter 中的 d != 1 , 4 0 5 不满足 c > 0 ,所以这 3 个索引项无需进行回表操作,也不需要返回给 Server 层
相信到这里,大家对 ICP 的 4 个问题应该就比较清楚了
ICP 的适用条件
虽说 ICP 能提高 SQL 执行效率,但也不是任何情况下都适用的,它只适用于某些情况
1、当 SQL 需要全表访问时,ICP 的优化策略可用于 range, ref, eq_ref, ref_or_null 类型的数据访问方式
2、只适用于 InnoDB 和 MyISAM 两种存储引擎
3、在 InnoDB 中,ICP 只适用于二级索引
ICP 的目的就是为了减少回表导致的磁盘 I/O,而 InnoDB 的聚簇索引的叶子节点存放的就是完整的数据记录,只要索引数据被读到内存了,那么索引项对应的完整数据记录也就读到内存了,那么通过索引项获取数据记录的过程就在内存中进行了,无需进行磁盘 I/O;也就说聚簇索引上应用 ICP,不会减少磁盘 I/O,也就没有使用的意义了
4、不支持覆盖索引
其实和第 3 点一样,因为覆盖索引无需回表,ICP 也就没意义了
5、不支持子查询条件的下推
6、不支持存储过程条件、触发器条件的下推
至于 ICP 的优化效果,取决于在存储引擎内通过 ICP 筛选掉的数据的比例,过滤掉的数据比例大,那就性能提升大,反之则性能提升小
总结
1、索引覆盖与回表
这两个往往是一起来考虑的,因为覆盖索引的目的就是减少因回表产生的磁盘 I/O,从而提高执行效率
在实际应用中,我们往往也需要考虑尽可能用覆盖索引来完成我们的 SQL 查询
2、ICP的四个问题
将什么从哪 Push Down 到哪,优化了什么
将 Index Filter 从 Server 层 Push Down 到了引擎层,减少了因回表产生的磁盘 I/O,也减少了与 Server 层的交互,提高了 SQL 执行效率
3、疑问点
为什么这么明显的优化策略到 MySQL 5.6 才引入,个人感觉很容易就能考虑到呀,MySQL 的开发者们是肿么肥事 ?