嵌套查询效率_sql嵌套查询例子

嵌套查询效率_sql嵌套查询例子嵌套查询的查询优化TableofContents1.嵌套查询的分类和优化概述2.Kim:OnOptimizinganSQL-likeNestedQuery2.1.嵌套查询的分类2.1.1.A类2.1.2.N类2.1.3.J类2.1.4.JA类2.1.5.D类2.2.嵌套查询的优化3.Kiessling,SQ

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

嵌套查询的查询优化

嵌套查询是 SQL 中表达能力很强的一种机制,既给应用带来了方便也给查询优化带来了很大的挑战。本文总结一下经典的单机系统对嵌套查询的优化。

1 嵌套查询的分类和优化概述

比较好的分类和处理了典型嵌套查询的经典文献是 Kim 的 On Optimizing an SQL-like Nested Query 1。不过 Kim 的算法很快被发现在特定场景下存在一些小缺陷,需要打补丁修复。例如 Ganski 等对此做了改进 2。SQL 语言的进化过程中不断引入的新特性,也会影响到嵌套查询的处理,例如某些系统支持的 LIMIT 语句。具体产品中的实现可以从 ORACLE 的博客中得到一些启示:34

2 Kim: On Optimizing an SQL-like Nested Query

Kim 定义了嵌套查询的 5 种基本形式并给出了转换算法。最后组合成一个通用算法来处理任意复杂的嵌套查询(一般称为嵌套查询的非嵌套化)。在一个 SQL 语句中访问多个表的典型机制为: 连接谓词(JOIN)、嵌套谓词、除法谓词。非嵌套化就是把其他两种形式的查询转换为 JOIN。嵌套谓词会形成 4 种形式的嵌套查询,而除法谓词会形成另 1 种形式的嵌套查询,因此总共是 5 种。考虑到除法几乎没有系统实现它,后续可以略过。

2.1 嵌套查询的分类

首先,定义嵌套的层数。如果查询中只有一个查询块(SELECT、FROM、WHERE),显然不存在嵌套查询,此时嵌套的层数为0。如果查询中有两个查询块,外查询的叫做外部块,内查询的叫做内部块,此时嵌套层数为1。查询块嵌套的层次数显然可以更多,而且一个 WHERE 条件中可以有多个嵌套的子查询。查询块的 FROM 子句后面可以出现多个表。WHERE 条件以及子查询的结果列也可以出现多个,例如:(SNO, SNAME) = (SELECT SNO, SNAME FROM SUPPLY)。Kim 划分嵌套查询种类是从子查询有没有连接条件以及聚集函数这两个角度考虑的。

2.1.1 A 类

内查询块没有对外查询块的表的引用(非相关子查询),并且查询结果是聚集函数(不带 GROUP BY,结果集是单行)。

SELECT SNO
FROM SHIPMENT
WHERE PNO = (SELECT MAX(PNO)
             FROM PART
             WHERE PRICE > 25)

SELECT SNO FROM SHIPMENT WHERE PNO = (SELECT MAX(PNO) FROM PART WHERE PRICE > 25)

2.1.2 N 类

内查询块没有对外查询块的表的引用(非相关子查询),并且查询结果没有聚集函数(结果集是很可能是多行)。

SELECT SNO
FROM SHIPMENT
WHERE PNO IN (SELECT PNO
              FROM PART
              WHERE PRICE > 25)

SELECT SNO FROM SHIPMENT WHERE PNO IN (SELECT PNO FROM PART WHERE PRICE > 25)

2.1.3 J 类

内查询块有对外查询块的表的引用(相关子查询),并且查询结果没有聚集函数。

SELECT SNO
FROM SHIPMENT
WHERE PNO IN (SELECT PNO
              FROM PROJECT
              WHERE SHIPMENT.SNO = PROJECT.JNO AND JLOC = 'NEW YORK')

SELECT SNO FROM SHIPMENT WHERE PNO IN (SELECT PNO FROM PROJECT  WHERE SHIPMENT.SNO = PROJECT.JNO AND JLOC = 'NEW YORK')

2.1.4 JA 类

内查询块有对外查询块的表的引用(相关子查询),并且查询结果集有聚集函数。

SELECT SNO
FROM SHIPMENT
WHERE PNO = (SELECT MAX(PNO)
             FROM PROJECT
             WHERE PROJECT.JNO = SHIPMENT.JNO AND JLOC = 'NEW YORK')

SELECT SNO FROM SHIPMENT WHERE PNO = (SELECT MAX(PNO) FROM PROJECT  WHERE PROJECT.JNO = SHIPMENT.JNO AND JLOC = 'NEW YORK')

2.1.5 D 类

连接谓词与除法谓词一起形成的查询中,带有两个内查询块。任何一个的连接谓词引用了外查询块都会形成 D 型嵌套查询。

SELECT SNAME
FROM SUPPLIER
WHERE (SELECT PNO
       FROM SHIPMENT
       WHERE SHIPMENT.SNO = SUPPLIER.SNO)
      CONTAINS
      (SELECT PNO
       FROM PART
       WHERE COLOR = 'RED' AND PRICE > 25)

2.2 嵌套查询的优化

如果采用最简单直接的执行算法,对外查询块的每条记录,需要执行内查询块一次。A 类查询的子查询可以只计算一次,因此不再需要做特殊的转换或优化。N 类没有这么直接的优化,有必要做优化。J、JA、D 类存在类似的问题。

N 类的嵌套查询可以被等价转换为连接。对于子查询可能会产生的重复值,可通过 semi-join 来消除。op 可以是 IN 或标量操作符。(注意,标量运算符要求结果集是单行。)嵌套1层的转换算法比较直接,命名为 NEST-N-J。J 类的嵌套查询也可以用类似的算法来转换。对于 NOT IN 操作符,要采用 anti-join。而且,对于 J 类的查询,还要确保 anti-join 的计算是发生在 join 条件之后。

JA 类的查询可以引入一个做聚集运算的临时表来等价转换为 J 类查询,算法命名为 NEST-JA。op 是个标量操作(因此不需要考虑重复值),查询最终被转换为 join。多层嵌套的 JA 类查询也可以被转换为 J 类查询。

3 Kiessling, SQL-Like and Quel-like correlation queries with aggregates revisited

4 Ganski, Wong: Optimization of Nested SQL Queries Revisited

解决了 Kim 算法 NEST-JA 中的缺陷,并扩展到 SQL 中常见的子句,包括 EXISTS、NOT EXISTS、ANY、ALL 等。

4.1 COUNT

SELECT PNUM FROM PARTS WHERE QOH = (SELECT COUNT(SHIPDATE) FROM SUPPLY WHERE SUPPLY.PNUM = PARTS.PNUM AND SHIPDATE < ‘1-1-80’)

算法引入的临时表在处理聚集函数时会丢失掉记录,从而导致最终结果少了。临时表丢失记录的问题可以通过外连接解决。如果内查询中用的是 COUNT(*),还需要在转换时改成 COUNT(col),以避免因为外连接引入的 NULL 导致的计数增加。

4.2 非等值条件

类似的,非等值条件也存在丢失信息的问题,也可以通过连接来解决(如果是 COUNT,则要用外连接)。

4.3 重复值

如果连接的列上有重复值,连接操作会放大结果集的记录数。不过它们只可能影响 COUNT、AVG、SUM,而不会影响 MAX、MIN。在产生临时表之前还要加一步,投影去掉连接列上的重复值。

5 总结

容易发现,嵌套查询的非嵌套化未必是最优的,Kim 等的论文中都有代价分析。逐步改进(打补丁)的做法也逐步增加了转换后查询的处理代价,需要代价优化器来判断转换是否有必要。

Footnotes:

1 

Kim, On Optimizing an SQL-like Nested Query.

2 

R.A. Ganski etc., Optimization of nested SQL queries revisited.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/179722.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • eclipse汉化版使用教程(安卓市场(官方版本))

    Eclipse汉化教程1.确定Eclipse的版本方法一:打开eclipse,在启动画面中可以看到eclipse的版本名称(我的版是Photon),记住这个版本的名称;方法二:在Eclipse启动后,点击菜单栏中的**Help(帮助)&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;gt;AboutEclipse(关于EclipseIDE)**会弹出的AboutEclipse窗口,在这里也可以找到当前Ec

    2022年4月16日
    187
  • 电子设计竞赛控制组——完整旋转倒立摆程序

    电子设计竞赛控制组——完整旋转倒立摆程序以前也想过要写博客,但是却一直没有付诸于实践,作为第一篇原创,我还是选择将以前电赛时的作品拿出来,毕竟当初可是花费了好多心血的,汗~旋转倒立摆是控制组校内赛练手的题目,需要对PID非常熟悉才能调好参数,以下代码是自己搭建好结构后调试出来的程序,其中的参数会根据不同的结构作出调整。结构组成:K60开发板(带液晶屏和按键),角度编码器,直流减速电机(带编码器),12V的电机驱动,金属摆臂,…

    2022年8月18日
    3
  • Python 学习笔记 列表 xxx XXX

    Python 学习笔记 列表 xxx XXXPython学习笔记列表xxxXXXbicycles=[‘trek’,’cannondale’,’redline’,’specialized’]print(bicycles)print(bicycles[0])print(bicycles[0].title())print(bicycles[-1])names=[‘wenwen’,’juanjuan’,’yuyu’]forxinnames: prin…

    2022年8月22日
    5
  • Intellij IDEA 实用插件

    Intellij IDEA 实用插件1.前言从2020年JVM生态报告解读可以看出IntellijIDEA目前已经稳坐JavaIDE头把交椅。而且统计得出付费用户已经超过了八成(国外统计)。IDEA的优良设计保证了我的生产力,也是我情愿为之付费的软件之一。今天把我自己经常用的一些插件拿出来分享一波。同时欢迎加入[微信圈子]SpringForAll社区交流编程经验。2.IDEA插件分享之前我们来看看其插件体系。IntellijIDEA大部分功能是通过插件集成进来的。默认情况下已经集成了很多插件。你可以…

    2025年5月23日
    2
  • vb调用access数据库(access追加查询键值冲突)

    VB连接access数据库时,在查询语句中需要使用like问题时注意1、officeaccess中查询的通配符“*”。SQL中通配符是“%”2、但在VB中使用时,为“%%”,不是“*”,也不是“**”转载于:https://www.cnblogs.com/xbj-hyml/p/6928695.html…

    2022年4月16日
    31
  • Windows Azure AppFabric应用程序

    Windows Azure AppFabric应用程序WindowsAzureAppFabric团队在大步前进。在上个月发布服务总线队列和Topics到CTP之后,这个团队刚刚发布AppFabric应用程序到CTP。AppFabric应用程序简化了将服务组成一个应用程序的任务,但实际上,它似乎重写了平台作为服务的意义(PaaS)

    2022年10月16日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号