视图重写和等价谓词重写

Posted NoctisYang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了视图重写和等价谓词重写相关的知识,希望对你有一定的参考价值。

还没看,先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.t2t12

明显可以看到后者的子查询没有被消除,而前者则完全成为了转化为对基表的查询,这里的结果明显前者优于后者。

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

 

以上是关于视图重写和等价谓词重写的主要内容,如果未能解决你的问题,请参考以下文章

javascript 不能接受视图中的输出重写

优化器

第五部分

现代等价于superiorto() 函数

如何在没有 DCG 的 L 系统启发的重写系统中进行递归

“equals”与“==”的区别-如何重写equals()和hashCode()方法