mysql5.7官网直译SQL语句优化--行结构表达式的优化

来源:互联网 发布:水晶古筝知乎 编辑:程序博客网 时间:2024/06/05 07:41
1.18Row Constructor Expression Optimization行结构表达式的优化
行结构允许同时比较多个列的值。例如,这两个语句的语义是相等的:
SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
而且优化器处理两个表达式的方式是一样的。
优化器很难有一个可用的索引,如果行结构列不能覆盖一个所以的前缀时。考虑如下的表,其中主键是一个联合(c1,c2,c3):
CREATE TABLE t1 (
  c1 INT, c2 INT, c3 INT, c4 CHAR(100),
  PRIMARY KEY(c1,c2,c3)
);
在这个查询中,where条件中使用了索引的全部列。然而,行结构表达式自己并没有覆盖一个索引前缀,结果是优化器值能使用c1(key_len=4,c1的大小):
mysql> EXPLAIN SELECT * FROM t1
       WHERE c1=1 AND (c2,c3) > (1,1)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 3
     filtered: 100.00
        Extra: Using where
在这种情况下,重写行结构表达式使用一个等价的非行结构表达式使得结果完成的更有效。对于给出的查询,行结构表达式和等价的非行结构表达式是:
(c2,c3) > (1,1)
c2 > 1 OR ((c2 = 1) AND (c3 > 1))
重写了查询使用一个非结构表达式,优化器使用了在索引中的所有三个列(key_len=12):
mysql> EXPLAIN SELECT * FROM t1
       WHERE c1 = 1 AND (c2 > 1 OR ((c2 = 1) AND (c3 > 1)))\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 12
          ref: NULL
         rows: 3
     filtered: 100.00
        Extra: Using where
这样,为了更好的结果,避免使用行结构表达式和AND/OR表达式一起用,使用行结构表达式,或者是AND/OR。
在确定的条件下,优化器能够使用范围查找方法在IN()表达式,即使是有行结构表达式参数。请看行结构表达式中的范围扫描优化。
到此关于行结构表达式的优化就结束了,接下来我们要看的是1.19Avoiding Full Table Scans.
------------------------------
1.19避免全表扫描。
当mysql使用了全表扫描的时候,我们可以在EXPLAIN的输出中看到type列的值为ALL.这通常发生在下列条件:
1)表很小,所以很快就能完成全表扫描,而不需要麻烦到索引扫描。通常来说行数小于10行,并且行的长度不长。
2)没有使用限制在on或者是where条件中对索引列。
3)你能够对比被索引的值用常量值并且mysql已经计算(基于索引树)常量值覆盖的表的大部分,那样的话表扫描会更快。请看8.2.1.1的where 条件优化。
4)你使用索引通过另一个列的小基数。在这种情况下,mysql假设通过使用索引会扫描很多行,并且表扫描会更快。
对于小表,一个表扫描通常是合适的,并且性能影响几乎可以忽略。对于大表,试着用下面的方法来避免优化器错误的选择一个全表扫描。
>使用ANALYZE TABLE tb1_name去更新键值分布为了扫描表。具体请看13.7.2.1的分析表的语法。
>使用FORCE INDEX 对于要扫描的表,告诉mysql全表扫描的代价要比使用给出的索引大很多:
SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
  WHERE t1.col_name=t2.col_name;
请看8.9.3的索引提示。
>启动mysqld 用--max-seeks-for-key=1000选项,或者是设置max_seeks_for_key=1000去告诉优化器设定没有键扫描导致多余1000次的键查找。具体请看5.1.5服务器系统变量设置。
到此关于8.2.1的select语句优化就结束了。接下来我们要开始的是8.2.2 Optimizing Subqueries,Derived Tables,and View References;
阅读全文
0 0
原创粉丝点击