索引存取类型
考虑如下的查询语句:SELECT column1 FROM Table1;如果column1是索引列, 优化器更有可能选择索引全扫描,而不是采用表全扫描。这是因为该索引覆盖了我们所需要查询的列。
再考虑如下的查询语句:
SELECT column1,column2 FROM Table1; 如果索引的定义如下,那么就可以使用索引全扫描:
CREATE INDEX … ON Table1(column1,column2);
也就是说,所有需要查询的列必须在索引中出现。但是如下的查询就只能走全表扫描了: select col3 from Table1;由于col3没有建立索引所以只能走全表扫描。
转换
MySQL对简单的表达式支持转换。比如下面的语法:
WHERE -5 = column1转换为: WHERE column1 = -5 尽管如此,对于有数学运算存在的情况不会进行转换。
比如下面的语法:
WHERE 5 = -column1不会转换为:WHERE column1 = -5,所以尽量减少列上的运算,而将运算放到常量上
AND
带AND的查询的格式为: AND ,考虑如下的查询语句:
WHERE column1=’x’ AND column2=’y’
优化的步骤:
1) 如果两个列都没有索引,那么使用全表扫描。
2) 否则,如果其中一个列拥有更好的存取类型(比如,一个具有索引,另外一个没有索引;再或者,一个是唯一索引,另外一个是非唯一索引),那么使用该列作为驱动表达式
OR
带OR的查询格式为: OR ,考虑如下的查询语句:WHERE column1=’x’ OR column2=’y’
优化器做出的选择是采用全表扫描。当然,在一些特定的情况,可以使用索引合并,这里不做阐述。如果两个条件里面设计的列是同一列,那么又是另外一种情况,考虑如下的查询语句:WHERE column1=’x’ OR column1=’y’在这种情况下,该查询语句采用索引范围查找
UNION
所有带UNION的查询语句都是单独优化的,考虑如下的查询语句:以下是引用片段:
SELECT * FROM Table1 WHERE column1='x'
UNION ALL SELECT * FROM Table1 WHER column2='y'
order by
一般而言,ORDER BY的作用是使结果集按照一定的顺序排序,如果可以不经过此操作就能产生顺序的结果,可以跳过ORDER BY操作。考虑如下的查询 语句:
SELECT column1 FROM Table1 ORDER BY ‘x’;优化器将去除该ORDER BY子句,因为此处的ORDER BY 子句没有意义。再考虑另外的一个查询语句:SELECT column1 FROM Table1 ORDER BY column1;在这种情况下,如果column1类上存在索引,优化器将使用该索引进行全扫描,这样产生的结果集是有序的,从而不需要进行ORDER BY操作。
再考虑另外的一个查询语句:SELECT column1 FROM Table1 ORDER BY column1+1; 假设column1上存在索引,我 们也许会觉得优化器会对column1索引进行全扫描,并且不进行ORDER BY操作。实际上,情况并不是这样,优化器是使用column1列上的索引进行全扫表,仅仅是因为索引全扫描的效率高于表全扫描。对于索引全扫描的结果集 仍然进行ORDER BY排序操作
GROUP BY
这里列出对GROUP BY子句以及相关集函数进行优化的方法:
1) 如果存在索引,GROUP BY将使用索引。
2) 如果没有索引,优化器将需要进行排序,一般情况下会使用HASH表的方法
3) 如果情况类似于“GROUP BY x ORDER BY x”,优化器将会发现ORDER BY子句是没有必要的,因为GROUP BY产生的结果集是按照x进行排序的
4) 尽量将HAVING子句中的条件提升中WHERE子句中。
5) 对于MyISAM表,“SELECT COUNT(*) FROM Table1;”
直接返回结果,而不需要进行表全扫描。但是对于InnoDB表,则不适合该规则。补充一点,如果column1的定义是NOT NULL的,那么语句“SELECT COUNT(column1) FROM Table1;” 等价于“SELECT COUNT(*) FROM Table1;” 。
6) 考虑MAX()以及MIN()的优化情况。考虑下面的查询语句:以下是引用片段:
SELECT MAX(column1) FROM Table1 WHERE column1<’a’; 如果column1列上存在索引,优化器使用’a’进行索引定位,然后返回前一条记录。
7) 考虑如下的查询语句: