视图重写和等价谓词重写
还没看,先mark一下
一、什么是视图重写?
视图是数据库中基于表的一种对象,把对表的查询固化,这种固化就是视图。
这里我们需要注意区分: 视图<——>物化视图<——>物化(技术),三者之间的关系。
物化是将结果缓存至内存的方式,这里我们所说的视图,其结果是动态的,而物化视图的结果是一个固定结果,对于物化技术来说,是实现将结果放置于内存的技术手段。 创建视图的格式为:
从这个格式这里我们理解下视图的定义,是基于表的,是一个对查询操作的结果的固化,这里我们说子查询实际上是说,视图的优化绝大部分都是可以转化为子查询的优化。 视图的类型:
1)用SPJ格式构造的视图,称为简单视图
CREATE VIEW v1 AS SELECT x, y, z FROM t;
2)用非SPJ格式构造的视图(带有GROUPBY等操作),称为复杂视图
CREATE VIEW v2 AS SELECT x, y, z FROM t ORDER BY x;
什么是视图重写?
1)查询语句中出现视图对象;
2)查询优化后,视图对象消失;
3)消失的视图对象的查询语句, 融合到初始查询语句中。
这里首先是说存在视图为前提,优化后视图被转化为子查询并且融合到原查询语句中。
例如:
这里基于t_a表创建了一个视图v_a,然后基于视图查询满足条件为字段col_b>100的字段col_a的数值。经过分析后,视图重写为如上形式,最后,等价变化为基于表t_a的,然后基于视图查询满足条件为字段col_b>100的字段col_a的数值。从而我们得到视图重写的准则:
1)MySQL支持对视图进行优化;
2)优化方法是把视图转为对基表的查询,然后进行类似子查询的优化;
3)MySQL通常只能重写简单视图,复杂视图不能重写。
二、对于MySql来说如何使用视图重写优化视图?
基于优化准则,我们通过几个实例开看下优化是如何达到的。
1)在简单视图上执行连接操作
直接用视图和表做连接操作,查询执行计划如下:
这里我们可以看到,视图在被优化后,视图消失了,并且成为了基表的一部分子查询。
然后,我们对比下,在表上执行与简单视图等价的连接操作:
对比下最后的处理后的语句:
前者:
from tt
.t1
join tt
.t1
join tt
.t2
后者:
from tt
.t1
join (
/* select#2 */ select tt
.t1
.a1
AS a1
,tt
.t1
.b1
AS b1
,
`tt`.`t2`.`a2` AS `a2`,`tt`.`t2`.`b2` AS `b2`
from tt
.t1
join tt
.t2
) t12
明显可以看到后者的子查询没有被消除,而前者则完全成为了转化为对基表的查询,这里的结果明显前者优于后者。
2)在简单视图上进行聚集操作
基于表t1和t2的视图v_t_1_2,进行聚集操作:
这里子查询没有被消除,但是视图转化为了子查询,优化完成。
3)直接用视图和表做连接操作,并执行分组操作
视图消失,转化为基于基表的子查询。
4)直接用视图和表做连接操作,并执行分组和去重操作操作
视图消失,转化为基于基表的子查询。
5)在简单视图上执行外连接操作
视图消失,转化为基于基表的子查询。
6)直接用复杂视图和表做连接操作
视图完全没有被转化,复杂视图无法被优化。
三、什么是等价谓词重写?
把逻辑表达式重写成等价的且效率更高的形式。优点是能有效提高查询执行效率,这里说的谓词实际就是我们平常使用的比如:in、like、or、not等。
四、对于MySql来说如何实现等价谓词重写?
常见的等价谓词重写有:
1)LIKE规则
LIKE谓词,是SQL标准支持的一种模式匹配比较操作;
LIKE规则,是对LIKE谓词的等价重写,即改写LIKE谓词为其他等价的谓词,以更好地利用索引进行优化。 示例如:
name LIKE ‘Abc%’
重写为:
name >=’Abc’ AND name <’Abd’
应用LIKE规则的好处:
转换前针对LIKE谓词,只能进行全表扫描,如果name列上存在索引,则转换后可以进行索引扫描。
LIKE其他形式还可以转换,例如:
LIKE匹配的表达式中,没有通配符(%或_),则与“=”等价,
如:
name LIKE ‘Abc’
重写为:
name =’Abc’
如果name列上存在索引,则可以利用索引提高查询效率。
2)BETWEEN-AND规则
BETWEEN-AND谓词,是SQL标准支持的一种范围比较操作;
BETWEEN-AND规则,是BETWEEN-AND谓词的等价重写,即改写BETWEEN-AND谓词为其他等价的谓词,以更好地利用索引进行优化。
例如:
sno BETWEEN 10 AND 20
重写为:
sno>=10 AND sno <=20
应用BETWEEN-AND规则的好处是:
如果sno上建立了索引,则可以用索引扫描代替原来BETWEEN-AND谓词限定的全表扫描,从而提高了查询的效率。
3)IN转换OR规则
说明:IN是只IN操作符操作,不是IN子查询。
IN转换OR规则,就是IN谓词的OR等价重写,即改写IN谓词为等价的OR谓词,以更好地利用索引进行优化。将IN谓词等价重写为若干个OR谓词,可能会提高执行效率。
例如:
age IN (8,12,21)
重写为:
age=8 OR age=12 OR age=21
应用IN转换OR规则后效率是否能够提高,需要看数据库对IN谓词是否只支持全表扫描。
如果数据库对IN谓词只支持全表扫描且OR谓词中表的age列上存在索引,则转换后查询效率会提高。
将IN谓词等价重写为ANY谓词,可能会提高执行效率。
例如:
age IN (8,12,21)
重写为: age ANY(8, 12, 21)
应用IN转换ANY规则后效率是否能够提高,依赖于数据库对于ANY操作的支持情况。
4)OR转换ANY规则
OR转换ANY规则,就是OR谓词的ANY等价重写,即改写OR谓词为等价的ANY谓词,以更好地利用MIN/MAX操作进行优化。
例如:
sal>1000 OR
dno=3 AND (sal>1100 OR sal>base_sal+100) OR
sal>base_sal+200 OR
sal>base_sal×2
重写为:
dno=3 AND (sal>1100 OR sal>base_sal+100) OR
sal> ANY (1000,base_sal+200,base_sal×2)
OR转换ANY规则,依赖于数据库对于ANY操作的支持情况。
PostgreSQL V9.2.3和MySQL V5.6.10目前都不支持本条规则。
5)ALL/ANY转换集函数规则
ALL/ANY转换集函数规则,就是ALL/ANY谓词改写为等价的聚集函数MIN/MAX谓词操作,以更好地利用MIN/MAX操作进行优化。
例如:
sno>ANY(10, 2*5+3,sqrt(9))
重写为:
sno>sqrt(9)
上面这个ALL/ANY转换集函数规则的示例,有两点需要注意:
1)示例中存在“>”和“ANY”,其意是在找出“(10, 2*5+3,sqrt(9))”中的最小值,所以可以重写为“sno>sqrt(9)”。
通常,聚集函数MAX()、MIN()等的执行效率一般都比ANY、ALL谓词的执行效率高,因此在这种情况下对其进行重写,可以起到比较好的效果。
2)如果有索引存在,求解MAX/MIN的效率更高。
6)NOT规则
NOT谓词的等价重写,如下:
NOT (col_1 !=2) 重写为 col_1=2
NOT (col_1 !=col_2)重写为 col_1=col_2
NOT (col_1 =col_2) 重写为 col_1!=col_2
NOT (col_1 <col_2) 重写为 col_1>=col_2
NOT (col_1 >col_2) 重写为 col_1<=col_2
NOT规则重写的好处:
如果col_1上建立了索引,则可以用索引扫描代替原来的全表扫描,从而提高查询的效率。
7)OR重写并集规则
OR条件重写为并集操作,形如下SQL示例:
SELECT *
FROM student
WHERE(sex=’f’ AND age>15) OR age>18;
假设所有条件表达式的列上都有索引(即sex列和age列上都存在索引),数据库可能对于示例中的WHERE语句强迫查询优化器使用顺序 扫描,因为这个语句要检索的是OR操作的集合。
为了能利用索引处理上面的查询,可以将语句改成如下形式:
SELECT *
FROM student
WHERE sex=’f’ and age>15
UNION
SELECT *
FROM student
WHERE age>18;
改写后的形式,可以分别利用列sex和age上的索引,进行索引扫描,然后再提供执行UNION操作获得最终结果。
总结,视图重写可以将视图转化为基于基表的子查询,而谓词重写则可以为诸如建立索引提高性能而提供帮助,但是,实际会不会提高性能还需要根据数据库本身的支持度再去考量,不是万能的准则。
转载地址:http://xn--m8tz91bfdr2pjzo.xyz/%E8%A7%86%E5%9B%BE%E9%87%8D%E5%86%99%E5%92%8C%E7%AD%89%E4%BB%B7%E8%B0%93%E8%AF%8D%E9%87%8D%E5%86%99/?nsukey=chhBgRX3EAKcRyKGfljlqa%2F4ZT1MHm2KTgqwIPVs6ExhqY%2F6y74%2FP%2B9goM2K2jwZxsMU53GibSwJb8zhHntEFujtLAXR23huzT6M1QtAVrKex5yK6mINQ0pT%2Bh41oEE0GHi9IN0fEOLqNkF8hk4IENPpGHS1ToYPhzVG3ABrRP4PHT46CgqpS6MSjLfYZW%2B5