1)LIKE规则
如:name like 'abc%'
重写为
name >= 'abc' and name < 'abd';
应用like规则的好处:转换前针对 like 谓词只能进行全表扫描。如果name列上存在索引,则转换后可以进行索引范围扫描。
如果没有通配符(%或_)。则是与 = 等价
name like 'abc'
重写为
name = 'abc'
2) BETWEEN-AND规则
sno BETWEEN 10 AND 20
重写为
sno >= 10 and sno <=20
好处:如果sno建立了索引,则可以用索引扫描代替原来的BETWEEN-AND谓词限定的全表扫描,从而提高了查询的效率。
3)IN转换OR规则
IN只是IN操作符,而不是IN子查询。改为OR可以更好地利用索引进行优化。将IN改为若干个OR可能会提高效率。
age IN (8, 12, 21)
重写为
age = 8 or age = 12 or age = 21
效率是否提高,需要看数据库对IN谓词是否只支持全表扫描。如果数据库对IN谓词只支持全表扫描且OR谓词中表的age列存在索引,则转换后的查询效率会更好。
4)IN转换ANY规则
因为IN可以转换为OR,而OR可转换为ANY,所以可以直接把IN转换为ANY。这可能会提高效率。
age IN (8, 12, 21)
重写为
age any (8, 12, 21)
效率是否提高,依赖于数据库对ANY操作的支持情况。
如:PostgreSQL没有显式支持 ANY 操作,但在内部实现时把IN操作转换为了ANY操作。(通过 explain 知道)
5)OR转换为ANY规则
这样可以更好地利用 MIN/MAX 操作进行优化。但(PG9.2.3 和 MySQL 5.6.10 目前都还没有支持)
6)ALL/ANT 转换为集函数规则
这样可以更好地利用 MIN/MAX 操作进行优化。如:
sno > ANY (10, 2*5+3, sqrt(9))
重写为
sno > sqrt(9)
通常,聚集函数MAX(), MIN()等的效率比ANY, ALL谓词的执行效率高。
7)NOT规则
NOT (col_1 != 2) 重写为 col_1 = 2 其他类似
好处:如果 col_1 上建立了索引,则可以用索引扫描代替原来的全表扫描。
8)OR重写并集规则
如:
select * from student where ( sex = 'f' and sno > 15 ) or age > 18;
这条SQL会强迫查询优化器使用顺序存取,因为这个语句要检索的是OR操作的集合。假设,sex, age 上有索引,则可优化为:
select * from student where sex = 'f' and sno > 15 union select * from student where age > 18;