MYSQL的联合索引的使用

mysql的查询算法并没有oracle的优秀,有些查询严重依赖索引。

SQL如下

SELECT DISTINCT XFZMC
                   ,CSN
                   ,XB
                   ,SYQ
                   ,SYXZ
                   ,DYBJ
                   ,NLD
    FROM            succez_dfdw.fact_zdsj_tmp zdsj
    WHERE           NOT EXISTS(SELECT 1 FROM succez_dfdw.DFBA3_BASE_011 xfz where xfz.CONSUMERKEY = zdsj.XFZMC)
                     AND zdsj.XFZMC IS NOT NULL

我们首先一层层分析,fact_zdsj_tmp 表与DFBA3_BASE_011 表有关联,然后在取fact_zdsj_tmp 的数据。

很多人一看见有关联查询,想的就是把关联的字段加上索引。我当时也是这样想的,在CONSUMERKEY与XFZMC列上加上索引。

接下来我们看执行计划


奇怪,我已经在关联查询的XFZMC名称上加上了索引,为什么此处没有用到,mysql居然对fact_zdsj_tmp 还进行全表扫描,在90多秒没查询出数据的时候,我失去了耐心,中断了查询。

在翻阅高性能mysql一书后,我建立了XFZMC  CSN   XB  SYQ  SYXZ  DYBJ  NLD 字段的联合索引。接下来我们看执行计划


此时查询花费2秒。

造成这种原因是为什么?


首先解释一下执行计划的,通过执行计划我们可以看出数据库在执行sql是按照那些步骤来的。

我们先看最上面的一个执行计划截图。我们看见fact_zdsj_tmp  zdsj的type列的值是all,说明进行的是全表扫描,possible_keys是mysql觉得会使用哪些索引的名称,这里出现的XFZMC列的索引名称,key代表mysql实际会使用的索引。我们看到他是空,说明mysql并没有使用我们建立的索引。

这是因为mysql的优化器觉得此处进行一个全表扫描比较快,若使用刚才的XFZMC的索引来查,反而会变慢。

我们先看最下面的一个执行计划截图,key此处有值了,就是我们建立的联合索引,进行了range(范围扫描)。


接下来给大家粗略的讲解一下索引的运行过程。

很多人以为给表的字段加个ID主键列就可以标志这是一条唯一的数据了,在我看来,这只是逻辑上的。我认为,在物理上,表的数据都存在我们电脑的硬盘上,我这里用rowid代表他在磁盘的位置,哪个扇区,哪个磁道,哪个块上。索引是一个树的结构,一个节点就保存着我们的rowid与建立的索引列的值。

在这里我又要举个例子了,我们把人的基本信息作为一张表 ,这张表有性别,身份证号,名字,家庭人口数量。 身份证看做我们的一个索引的节点结构,我们在身份证号上建立了索引。在身份证上(索引上)家庭住址相当于rowid,身份证号码420983***********1234就是我们人的基本信息表中身份证号码的值。

现在,一个警察在大街上看见了你,他想知道你的家庭人口,而此时你没有带身份证,你给出了你的身份证号码。他通过在公安系统的身份证上查,通过身份证号得到了你的身份证上的家庭住址,警察去了你家,得到了家庭人口为4人。上面的一个例子中,我们只给xfzmc加了索引,mysql通过索引节点(也是 一个块)找到了rowid,通过rowid扫描了块。在块中找了XB  NLD等其他列。

此时警察再想,我要是不用去他家就好了。这还不简单,我们在家庭人口刻录在身份证上面,通过你的身份证直接得到了家庭人口为4,就不用去你的家了。

在此时建立联合索引便是同样的一个道理。我们把其他列的值都放在了一个块中,就不用去扫描两个块了。I/O消耗降低了。这就是为什么上面建立了联合索引变快了。


实际上,联合索引是有两个特性的。在web系统中,我们常和这样的界面打交道



我们根本不知道用户会选择输入哪些文本框,我们应该在哪些字段加上加索引呢?

利用好联合索引的两个特性,我们就能很好的提高页面的加载速度了。

关于联合索引的两个特性,下次在讲。


   


你可能感兴趣的:(MYSQL的联合索引的使用)