在编写查询之前,我们甚至应该对过滤条件进行排序,真正高效的条件(可能有多个,涉到同的表)是查询的主要驱动力,低效条件只起辅助作用。那么定义高效过滤条件的准则是什呢?首先,要看过滤条件能否尽快减少必须处理的数据量。所以,我们必须倍加关注条件
在编写查询之前,我们甚至应该对过滤条件进行排序,真正高效的条件(可能有多个,涉到同的表)是查询的主要驱动力,低效条件只起辅助作用。那么定义高效过滤条件的准则是什呢?首先,要看过滤条件能否尽快减少必须处理的数据量。所以,我们必须倍加关注条件的写方式。
假设有四个表: customers 、 orders 、 orderdetail 、 articles ,现在假设 SQL 要处理的问题是:找出最近六个月内居住在 Gotham 市、订购了蝙蝠车的所有客户。当然,编写这个查询有多种方法, ANSI SQL 的推崇者可能写出下列语句:
select distinct c.custname from customers c join orders o on o.custid = c.custid join orderdetail od on od.ordid = o.ordid join articles a on a.artid = od.artid where c.city = 'GOTHAM' and a.artname = 'BATMOBILE' and o.ordered >= somefunc
其中, somefunc 是个函数,返回距今六个月前的具体日期。注意上面用了 distinct ,因为考虑到某个客户可以是大买家,最近订购了好几台蝙蝠车。
暂不考虑优化器将如何改写此查询,我们先看一下这段代码的含义。首先,来自 customers 表的数据应只保留城市名为 Gotham 的记录。接着,搜索 orders 表,这意味着 custid 字段最好有索引,否则只有通过排序、合并或扫描 orders 表建立一个哈希表才能保证查询速度。对 orders 表 ,还要针对订单日期进行过滤:如果优化器比较聪明,它会在连接( join )前先过滤掉一些数据,从而减少后面要处理的数据量;不太聪明的优化器则可能会先做连接,再作过滤,这时在连接中指定过滤条件利于提高性能,例如:
join orders o on o.custid = c.custid and a.ordered >= somefunc
注意,如果是:
left outer join orders o on o.custid = c.custid and a.ordered >= somefunc
此处关于left表的筛选条件将失效,因为是左外连接,左表的所有列都将出现在这次连接结果集中)。
即使过滤条件与连接( join )无关,优化器也会受到过滤条件的影响。例如,若 orderdetail 的主键为( ordid, artid ),即 ordid 为索引的第一个属性,那么我们可以利用索引找到与订单相关的记录。但如果主键是( artid, ordid )就太不幸了(注意,就关系理论而言 ,无论哪个版本都是完全一样),此时的访问效率比( ordid, artid )作为索引时要差,甚至一些数据库产品无法使用该索引(注 3 ),唯一的希望就是在ordid 上加独立索引了。
连接了表 orderdetail 和 orders 之后,来看 articles 表,这不会有问题,因为表 order 包括 artid 字段。最后,检查 articles 中的值是否为 Batmobile 。查询就这样结束了,因为用了 distinct ,通过层层筛选的客户名还必须要排序,以剔除重复项目。
避免在最高层使用 distinct 应该是一条基本规则 。原因在于,即使我们遗漏了连接的某个条件, distinct 也会使查询 " 看似正确 " 地执行 —— 无可否认,发现重复数据容易,发现数据不准确很难,所以避免在最高层使用 distinct 应该是一条基本规则。
发现结果不正确更难,例如,如果恰巧有多位客户都叫 " Wayne " , distinct 不但会剔除由同个客户的多张订单产生的重复项目,也会剔除由名字相同的不同客户产生的重复项目。事实上,应该同时返回具唯一性的客户 ID 和客户名,以保证得到蝙蝠车买家的完整清单。
要摆脱 distinct ,可考虑以下思路:客户在 Gohtam 市,而且满足存在性测试,即在最近六个月订购过蝙蝠车。注意,多数(但非全部) SQL 方言支持以下语法:
select c.custname from customers c where c.city = 'GOTHAM' and exists (select null from orders o, orderdetail od, articles a where a.artname = 'BATMOBILE' and a.artid = od.artid and od.ordid = o.ordid and o.custid = c.custid and o.ordered >= somefunc )
上例的存在性测试,同一个名字可能出现多次,但每个客户只出现一次,不管他有多少订单。有人认为我对 ANSI SQL 语法的挑剔有点苛刻(指 " 蝙蝠车买主 " 的例子),因为上面代码中customers 表的地位并没有降低。其实,关键区别在于,新查询中 customers 表是查询结果的唯一来源(嵌套的子查询会负责找出客户子集),而先前的查询却用了 join 。
这个嵌套的子查询与外层的 select 关系十分密切。如代码第 11 行所示(粗体部分),子查询参照了外层查询的当前记录,因此,内层子查询就是所谓的关联子查询( correlated subquery )。
此类子查询有个弱点,它无法在确定当前客户之前执行。如果优化器不改写此查询,就必须先找出每个客户,然后逐一检查是否满足存在性测试,当来自 Gotham 市的客户非常少时执行效率倒是很高,否则情况会很糟(此时,优秀的优化器应尝试其他执行查询的方式)。
select custname from customers where city = 'GOTHAM' and custid in (select o.custid from orders o, orderdetail od, articles a where a.artname = 'BATMOBILE' and a.artid = od.artid and od.ordid = o.ordid and o.ordered >= somefunc)
在这个例子中,内层查询不再依赖外层查询,它已变成了非关联子查询( uncorrelated subquery ),只须执行一次。很显然,这段代码采用了原有的执行流程。在本节的前一个例子 中 ,必须先搜寻符合地点条件的客户(如均来自 GOTHAM ),接着依次检查各个订单。而现在,订购了蝙蝠车的客户,可以通过内层查询获得。
不过,如果更仔细地分析一下,前后两个版本的代码还有些更微妙的差异。含关联子查询的代码中,至关重要的是 orders 表中的 custid 字段要有索引,而这对另一段代码并不重要,因为这时要用到的索引(如果有的话)是表 customers 的主键索引。
你或许注意到,新版的查询中执行了隐式的 distinct 。的确,由于连接操作,子查询可能会返回有关一个客户的多条记录。但重复项目不会有影响,因为 in 条件只检查该项目是否出现在子查询返回的列表中,且 in 不在乎某值在列表中出现了一次还是一百次。但为了一致性,作为整体,应该对子查询和主查询应用相同的规则,也就是在子查询中也加入存在性测试:
select custname from customers where city = 'GOTHAM' and custid in (select o.custid from orders o where o.ordered >= somefunc and exists (select null from orderdetail od, articles a where a.artname = 'BATMOBILE' and a.artid = od.artid and od.ordid = o.ordid))
或者
select custname from customers where city = 'GOTHAM' and custid in (select custid from orders where ordered >= somefunc and ordid in (select od.ordid from orderdetail od, articles a where a.artname = 'BATMOBILE' and a.artid = od.artid)
尽管嵌套变得更深、也更难懂了,但子查询内应选择 exists 还是 in 的选择规则相同:此选择取决于日期与商品条件的有效性。除非过去六个月的生意非常清淡,否则商品名称应为最有效的过滤条件,因此子查询中用 in 比 exists 好,这是因为,先找出所有蝙蝠车的订单、再检查销售是否发生在最近六个月,比反过来操作要快。如果表 orderdetail 的 artid 字段有索引,这个方法会更快,否则,这个聪明巧妙的举措就会黯然失色。
每当对大量记录做存在性检查时,选择 in 还是 exists 须斟酌。
利于多数 SQL 方言,非关联子查询可以被改写成 from 子句中的内嵌视图。然而,一定要记住的是, in 会隐式地剔除重复项目,当子查询改写为 from 子句中的内嵌视图时,必须要显式地消除重复项目。例如:
select custname from customers where city = 'GOTHAM' and custid in (select o.custid from orders o, (select distinct od.ordid from orderdetail od, articles a where a.artname = 'BATMOBILE' and a.artid = od.artid) x where o.ordered >= somefunc and x.ordid = o.ordid)
总结:保证 SQL 语句返回正确结果,只是建立最佳 SQL 语句的第一步。

iPhone16系列将在全线型号也采用堆叠式后置感光元件设计。该设计在今年的iPhone15标准版上已有类似的应用。今年的标准版iPhone15和iPhone15Plus预期将配备一个4800万像素的后置镜头,并使用能够捕捉更多光线的堆叠式CMOS影像感光元件(CIS)设计。新感光元件设计的产能问题,导致苹果无法在所有iPhone15型号上全面采用此设计。尽管索尼的高端CIS产能预期将在2024年前持续紧张,但Apple已提前确保了大部分的Sony订单。根据郭明錤的说法,索尼产能紧张,将对竞争对

在线投票系统的设计与实现随着互联网的不断发展,在线投票系统成为了一种非常方便和高效的方式来进行民意调查和选举。本文将介绍在线投票系统的设计和实现,并附带一些代码示例。一、系统设计功能需求分析在线投票系统主要具备以下功能:用户注册与登录:用户可以通过注册账号并登录系统来参与投票活动。创建投票:管理员可以创建投票并设定投票的相关参数,如投票主题、选项内容和投票截

随着互联网技术的发展,RESTful风格的API设计成为了最为流行的一种设计方式。而Java作为一种主要的编程语言,也越来越多地在RESTful接口的开发中扮演着重要的角色。在JavaAPI开发中,如何设计出优秀的RESTful接口,成为了一个需要我们深入思考的问题。RESTful接口的基本原则首先,我们需要了解RESTful接口的基本原则。REST即Re

随着互联网技术的不断发展,面向服务架构(SOA)的理念越来越受到人们的重视。在这个背景下,Go语言作为一种高效、可靠的编程语言,也逐渐成为了很多企业与开发者实现SOA的首选语言。本文将深入探讨Go语言中的面向服务架构设计。一、SOA简介面向服务架构是一种软件设计的架构风格,它将复杂的系统拆分成多个相互独立、可复用的服务,每个服务都有独立的功能实现,并使用标准

随着智能车辆在网联化、智能化及架构技术的发展,汽车无论是在固件还是软件上都已经不可逆转的需要进行软件迭代升级。要求在汽车生命周期内会不断的基于汽车OTA能力为整车提供软件升级、固件升级、售后服务等服务能力,可以说,汽车的智能化更迭对于OTA升级能力已经成为不可或缺的主流趋势。本文章将针对自动驾驶汽车的软件升级现状需求及监管要求等进行详细的描述。意在帮助读者整体了解自动驾驶中的软件升级过程原理、准入要求及其应对策略。1整车软件升级技术优势首先,软件定义汽车推动了整车软件升级技术的发展与应用,通过整

如何使用Go语言进行代码安全性设计在当今互联网时代,代码安全性是一项至关重要的任务。无论是为了保护用户的隐私还是避免遭受黑客攻击,代码安全性都是必不可少的。Go语言作为一种现代化的编程语言,提供了许多功能和工具,可以帮助我们进行代码安全性设计。本文将介绍一些在Go语言中实现代码安全性的最佳实践,并提供相应的代码示例。输入验证输入验证是代码安全性的第一道防线。

RESTfulAPI是目前Web架构中较为常用的一种API设计风格,它的设计理念是基于HTTP协议的标准方法来完成Web资源的表示与交互。在实现过程中,RESTfulAPI遵循一系列规则和约束,包括可缓存、服务器-客户端分离、无状态性等,这些规则保证了API的可维护性、扩展性、安全性以及易用性。接下来,本文将详细介绍RESTfulAPI的设计及其实现方

在互联网时代,文章阅读与分享已经成为人们日常生活中必不可少的一部分。然而,对于文章的点赞与收藏功能来说,用户体验体现的非常关键。而Redis作为一个高性能的键值存储数据库,在文章点赞与收藏功能的实现中有很大的优势。本文将分享一个基于Redis实现的文章点赞功能设计。功能设计文章点赞功能的设计过程中,需要考虑到许多因素。首先,需要将点赞接口暴露给用户,用户可随


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境
