Mysql中的单表访问方法与多种优化

90 阅读3分钟

单表访问方法

  • const 用唯一索引进行等值匹配 除了NULL(因为NULL不唯一,一般在表的最左边)
  • ref 在索引中存在一整块的扫描区间
  • ref_or_null select* from able where key1='abc' or key is null;
  • renge 对索引进行多个单点扫描或多个扫描区间
  • index 存在索引k1_k2时 select k1 from t where k2<2 可以扫描整个二级索引(如果用了order by也是这个方法)
  • all 全表扫描

索引合并

  • intersection 对于select* from t where k1='a' and k3='b';
    如果同时存在k1 k2两个索引时,我们会对两个索引同时进行查询,并合并找到id值相同的记录,在回表扫描。(以为单独的二级索引实质是关于k1和主键的二级索引)
    这主要是出于两个方面的考虑:
    从两个有序集合中获取交集比从无序集合中获取要简单的多
    如果id有序,那么根据这些id进行回表就不是随机IO,这样说速度快得多
    不过对于二级索引k_p来说,如果k相同,就会按p来排序,这样就不能进行合并了select * from t where k1='a' and k2>9000 也是如此,不过下面这种情况则比较特殊:
    select * from t where k1='a' and id>9000
    我们可以先用k1来查询,不断向右走,直到不满足上面两个情况为止。
  • Union 使用or来关联,情况差不多。
  • Sort-Union 索引合并 select * from t where k1<'a' or k3>'z'我们可以先从二级索引查出k1<a并根据主键排序,再查出k2<c再根据主键排序,然后再用union方法

连接原理

步骤:
首先确定第一个要查询的表,被称为驱动表,接下来每从驱动表中获得一条记录,都要在被驱动表中查找匹配的记录,所以在两表的连接中,被驱动表可能被查找多次。
内连接和外连接的最根本区别在于驱动表的记录不符合ON是,会不会将最后的结果加入最后的结果集中,在内连接中,驱动表和被驱动表示可以呼唤的,但外连接则不行。

where和on的区别

只要是不符合where的字句的,都不会被加入结果集
但在外连接中如果无法在被驱动表中找到符合ON字句的条件的,仍然会被加入结果集,没有的字段会被NULL填充。
在内连接中,on和wher是一样的。

对嵌套过滤循环的优化

MYSQL提出了一个join buffer的概念,就是在执行查询前申请一块内存,用来记录驱动表,接下来开始扫描被驱动表,每条记录都会一次性的与每一条join buffer中的表进行匹配,这是在内存中完成了,注意只有查询的和过滤条件的才会被放入join buffer中。

基于成本的优化

在MYSQL中,有两种主要成本:I/O成本与CPU成本,每读一条记录的成本是0.2,每对一页进行查询的成本是1(索引中每一个索引范围也是), 在每次进行查询的时候,会有如下几个步骤:

  • 根据索引条件,找出所有可能用到的索引
  • 计算全表扫描的代价
  • 计算使用不同索引的代价
  • 根据不同的代价进行比较