概述今天主要介绍mysql的ICP特性。很多人可能没有听说过。这里有一个实验可以帮助你加深理解。1.Index_Condition_PushdownIndexConditionPushdown(ICP)是MySQL使用索引从表中检索数据的一种优化。如果关闭了ICP,引擎层会通过索引在基表中寻找数据行,然后返回到MySQLServer层,然后对这些数据行进行WHERE后的条件过滤。ICP开启后,如果某些WHERE条件可以使用索引中的字段,MySQLServer会将这部分下推到引擎层。存储引擎通过索引条目评估索引条件,然后使用索引从表中读取满足条件的行。ICP可以减少引擎层访问基表的次数和MySQLServer访问存储引擎的次数。总之,ICP优化可以在引擎层过滤掉大量的数据,这无疑减少了对基表和mysql服务器的访问次数。ICP优化用于range、ref、eq_ref和ref_or_null访问方法,当这些方法需要访问整个表行时。此策略可用于INNODB和MyISAM表。2.实验首先,我们先从一个简单的实验开始,直观地了解ICP的作用。1.导入示例数据这里我们使用EmployeesSampleDatabase作为示例数据库。将下载的压缩包解压后,会看到一系列文件,其中employees.sql是导入数据的命令文件。执行#yum-yinstallbzip2#tar-xvfemployees_db-full-1.0.6.tar.bz2#mysql-uroot-pSHOWTABLES;employees表将用于下面的实验。2.创建联合索引。employees表包含员工的基本信息。表结构如下:mysql>DESCemployees.employees;这张表默认只有一个主索引,因为ICP只能作用于二级索引,所以我们创建一个二级索引:ALTERTABLEemployees.employeesADDINDEXfirst_name_last_name(first_name,last_name);这将创建first_name和last_name的联合索引。3.查询(启用ICP)为了清楚的看到查询性能,启用profiling并关闭querycache:SETprofiling=1;SETquery_cache_type=0;SETGLOBALquery_cache_size=0;然后看下面的查询:mysql>SELECT*FROMemployeesWHEREfirst_name='Mary'ANDlast_nameLIKE'%man';根据MySQL索引的前缀匹配原则,两者对索引的使用是一致的,即只有first_name使用索引,而last_name由于前缀模糊不能使用索引进行匹配。查询关系我执行了3次,结果如下:mysql>showprofiles;查看执行计划mysql>explainSELECT*FROMemployeesWHEREfirst_name='Mary'ANDlast_nameLIKE'%man';4、查询(禁用ICP)关闭ICP:SEToptimizer_switch='index_condition_pushdown=off';运行同一个查询三次后,结果如下:发生了一些有趣的事情。关闭ICP后,同样的查询花费的时间是之前的三倍多。我们用explain看看后者的执行计划:mysql>explainSELECT*FROMemployeesWHEREfirst_name='Mary'ANDlast_nameLIKE'%man';从启用ICP和关闭ICP的执行计划可以看出,区别在于Extra。当启用ICP时,就是Usingindexcondition;当ICP关闭时,它是Usingwhere。其中,Usingindexcondition是ICP提高查询性能的关键。下面解释ICP如何提高查询性能。3.原理ICP的原理只是简单的在存储引擎端过滤索引可以过滤的where条件,而不是把索引访问的结果全部拿过来放在服务器端进行where过滤。以上述查询为例,在没有ICP的情况下,先通过索引前缀从存储引擎中读取first_name为Mary的224条记录,然后在server段使用where过滤last_name的like条件;启用ICP后,由于last_nameLike过滤可以通过index字段进行,那么存储引擎内部会通过比较index和where条件来过滤掉不满足where条件的记录。这个过程不需要读取整条记录,同时只返回服务器过滤的6条记录,从而提高查询性能。1)不使用ICP时如何进行索引扫描(1)存储引擎读取下一行时,先读取索引元组(indextuple),然后使用索引元组在基表中定位读取(基表)获取整行数据。(2)server层判断where条件,如果行数据满足where条件,则使用,否则丢弃。(3)执行步骤1,直到最后一行数据。2)使用ICP时,如何进行索引扫描(1)存储引擎从索引中读取下一个索引元组。(2)存储引擎使用索引元组来评估下推索引条件。如果不满足where条件,存储引擎将处理下一个索引元组(回到上一步)。只有当索引元组满足下推索引条件时,才会继续从基表中读取数据。(3)如果满足下推索引条件,存储引擎通过索引元组定位到基表的行,读取整行数据返回给server层。(4)服务器层评估还没有下推到存储引擎层的where条件。如果行数据满足where条件,则使用,否则丢弃。用两张图来说明:关闭ICP在不支持ICP的系统中,索引只是作为数据访问。启用ICP当启用ICP优化时,存储引擎首先使用索引过滤可以过滤的where条件,然后使用索引进行数据访问。索引条件过滤掉的数据不需要读取,也不会返回给服务器。