18143453325 在线咨询 在线咨询
18143453325 在线咨询
所在位置: 首页 > 营销资讯 > 信息时代 > 嵌套子查询的优化(数据库)

嵌套子查询的优化(数据库)

时间:2022-11-06 22:30:01 | 来源:信息时代

时间:2022-11-06 22:30:01 来源:信息时代

    嵌套子查询的优化 : 优化嵌套查询语句,选择合理的查询计划。
在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌入另一个查询块的WHERE子句或HAVING短语的条件中,这种查询称为嵌套查询。例如查询借阅过书名以“计算机”开头的借阅者姓名,可以如下表示:
SELECT name /*外层查询或父查询*/
FROM BR WHERE bookno IN
(SELECT bookno /*内层查询或子查询*/
FROM BOOK
WHERE bname like'计算机');
在这个例子中,下层查询块SELECT bookno FROM BOOK WHERE bname like '计算机'是嵌套在上层查询块SELECT name FROM BR WHERE bookno IN的WHERE条件中的。上层的查询块称为外层查询或父查询,下层查询块称为内层查询或子查询。SQL语言允许多层嵌套查询,即一个子查询中还可以嵌套其他子查询。
嵌套查询分为相关嵌套子查询和不相关嵌套子查询。当子查询的查询条件中没有引用父查询中的属性,即子查询条件不依赖于父查询,这种嵌套子查询称为不相关子查询。上面的例子就是一个不相关子查询的例子。
对于不相关子查询,由于子查询条件中没有引用父查询的属性,因此子查询可以独立求出。不相关子查询的求解方法是由里向外逐层处理。具体地,有两类处理方法。
第一类处理方法是针对仅以比较运算符构造父查询条件的不相关子查询。这类查询的特点是,子查询有唯一取值。假设要查询与DB一书在同一个出版社出版的书目,由于DB只在一个出版社出版过,因此,可以用等号构造父查询条件。
SELECT bname
FROM BOOK
WHERE publishing_house=(SELECT publishing_house
FROM BOOK
WHERE bname='DB');
对于这种仅以比较运算符构成父查询条件的不相关子查询,可以作为两个独立的查询进行优化,求解时由里向外处理,即先执行子查询,子查询的结果用于建立其父查询的查找条件。例如对于上例,首先求解出出版DB一书的出版社,不妨假设是“机械工业出版社”,然后将其值代入父查询,求解“机械工业出版社”出版的所有图书。
第二类处理方法是针对其他不相关子查询的,查询优化器将其重写为连接查询。由于子查询可以独立求解,因此用子查询结果构成一张临时表T,将嵌套查询重写为父查询的关系与T的连接操作。例如对于前面查询借阅过书名以“计算机”开头的借阅者姓名的例子,首先求解子查询,找出以“计算机”开头的所有图书的编号,构成临时表T,然后将BR表和T表进行自然连接,得出查询结果。这一查询重写过程是在逻辑优化时完成的,物理优化时即可按照普通查询的物理优化进行。
如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询(correlated subquery)。例如查询刘婧借阅过的所有图书,可以如下表达:
SELECT bname
FROM BOOK
WHERE EXISTS
(SELECT*
FROM BR
WHERE bookno=BOOK.bookno
AND name='刘婧');
这就是一个相关子查询,概念上,我们可以在BOOK中依次取每条元组的bookno值,用此值去检查BR表。若BR中存在这样的元组,其bookno值等于此BOOK.bookno值,并且其name='刘婧',则取此BOOK.bname送入结果表。
相关嵌套查询的执行效率往往不高,因为对外层查询的每一条元组都要运行一次子查询,从而可能导致大量的随机磁盘I/O操作。因此,SQL优化器尽可能重写查询,将嵌套子查询转换成连接查询,通过有效的连接算法来避免昂贵的随机I/O操作。这与不相关嵌套子查询的第二种情况类似。
例如,上面的相关嵌套查询语句可以重写为下面的连接查询:
SELECT bname
FROM BOOK,BR
WHERE BR.bookno=BOOK.bookno
AND name='刘婧');
这个例子中的嵌套子查询非常简单。一般情况下,不能将嵌套子查询关系直接移入外层查询的FROM子句里,而是采用与不相关嵌套子查询的第二种情况类似的方法,建立一个包含嵌套查询结果的临时表,将这个临时表与外层查询进行连接。例如,下面形式的查询:
SELECT …
FROM R
WHERE Predl AND exists
(SELECT*
FROM S
WHERE Pred2)
其中Pred2是一组简单谓词的合取,可以重写为:
CREATE table T AS
SELECT distinct Related_Var
FROM S
WHERE Pred2_unrelated;

SELECT …
FROM R,T
WHERE Predl AND Pred2_related;
这里的Pred2 unrelated包含Pred2中所有不涉及相关变量的条件,Pred2 related是所有涉及相关变量的条件(条件中引用的关系会相应地重命名),Related Var是嵌套子查询的相关变量。
对于查询刘婧借阅过的所有图书的嵌套查询例子,该嵌套查询可转换为如下形式:
CREAT TABLE T AS
SELECT DISTINCT bookno
FROM BR WHERE name='刘婧';
SELECT bname
FROM BOOK,T
WHERE T.bookno=BOOK.bookno;
这种用连接查询(可能使用临时关系)去替代嵌套查询的过程称为去除相关。去除相关是嵌套查询优化的主要技术。为去除相关进行的查询重写是在逻辑优化过程中完成。但并不是所有相关嵌套查询都能很容易地去除相关,重写为连接查询。在无法转换的情况下,优化器只能将子查询当作一个独立的表达式进行优化,然后再进行相关执行。
显然,复杂嵌套子查询的优化是非常困难的。目前许多DBMS产品的查询优化器仅做了少量的去除相关工作,因此用户最好避免使用复杂的嵌套子查询。

74
73
25
news

版权所有© 亿企邦 1997-2022 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭