嵌套查询效率_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.

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 内存对齐的规则以及作用[通俗易懂]

    内存对齐的规则以及作用

  • 毫米波雷达跟激光雷达_毫米波雷达市场

    毫米波雷达跟激光雷达_毫米波雷达市场文章目录激光雷达超声波雷达摄像头毫米波雷达激光雷达激光雷达的波长介于750nm-950nm之间,以单线或多线束机制辐射光束,接收目标或环境的反射信号,以回波时间差和波束指向测量目标的距离和角度等空间位置参数。激光雷达主要优点如下:(1)波长短,测量精度高(2)多线束的探测,可以实现对场景的三维成像。激光雷达的主要缺点是:(1)抗干扰能力低,易受天气影响,在雨雪雾等天气的作用下,激光雷达使用受限。(2)激光发射、被测目标表面粗糙等因素都对测量精度有影响。(3)结构复杂,除激光

  • java枚举类型enum用法(java定义枚举常量类)

    文章目录枚举类的使用如何定义枚举类方式一:jdk5.0之前,自定义枚举类方式二:jdk5.0,可以使用enum关键字定义枚举类Enum类的主要方法toString()values()valueOf(StringobjName)使用enum关键字定义的枚举类实现接口的情况情况一:实现接口,在enum类中实现抽象方法情况二:让枚举类的对象分别实现接口中的抽象方法枚举类的使用枚举类的理解:类的对象只有有限个,确定的。我们称此类为枚举类当需要定义一组常量时,强烈建议使用枚举类如果枚举类中只有一个对象,则

  • IDEA主题设置&更换[通俗易懂]

    1,点击File—Settings—Appearance&Behavior—Apppearance

  • mysql基本sql语句大全(基础用语篇)_mysql查询语句汇总

    mysql基本sql语句大全(基础用语篇)_mysql查询语句汇总1.数据库存储引擎mysql>showvariableslike’%storage_engine%’;#查看mysql当前默认的存储引擎mysql>showengines;#查看存储引擎InnoDB存储引擎:默认引擎,最常用的。InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键;InnoDB是默认的MySQL引擎InnoDB特…

  • 基于51单片机的步进电机的控制

    基于51单片机的步进电机的控制前面笔者分享过基于51单片机的两种小车制作,我们利用的是L298N驱动控制电机转动,那么接下来,笔者给大家介绍两种利用51单片机控制步进电机的小程序。首先我们要如何使电机转动呢,源程序如下:#include&lt;reg52.h&gt;unsignedcharcodeF_Rotation[4]={0x02,0x04,0x08,0x10};//正转表格,换算成二进制00…

发表回复

您的电子邮箱地址不会被公开。

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