大数据量查询
Querying Large Quantities of Data
越快剔除不需要的数据,查询的后续阶段必须处理的数据量就越少,自然查询的效率就越高,这听起来显而易见。集合操作符(set operator)是这一原理的绝佳应用,其中的union使用最为广泛,我们经常看到通过union操作将几个表“粘”在一起。中等复杂程度的union语句较为常见,大多数被连接的表都会同时出现在union两端的select 语句中。例如下面这段代码:
select ... |
select ... |
另一个“查询条件用错了地方”的经典例子,和在含有 group by 子句的查询中进行过滤操作有关。你可以过滤分了组的字段,也可以过滤聚合(aggregate)结果(例如检查 count() 的结果是否小于某阈值),或者同时过滤两者;SQL 允许在 having 子句中使用这类条件,但应该在 group by 完成后才进行过滤(比如排序之后再进行聚合操作)。任何影响聚合函数(aggregate function)结果的条件都应放在 having 子句中,因为在 group by 之前无从知道聚合函数的结果。任何与聚合无关的条件都应放在 where 子句中,从而减少为进行group by而必须执行的排序操作所处理的数据量。
现在回过头来看客户与订单的例子,我承认先前处理订单的方法比较复杂。在订单完成之前,必须经历几个阶段,这些都记录在表orderstatus中,该表的主要字段有:ordid(订单ID)、status、statusdate(时间戳)等,主键由ordid和statusdate组成。我们的需求是列出所有尚未标记为完成状态的订单(假设所有交易都已终止)的下列字段:订单号、客户名、订单的最后状态,以及设置状态的时间。最终,我们写出下列查询,滤掉已完成的订单,并找出订单当前状态:
select c.custname, o.ordid, os.status, os.statusdate |
这个查询如何执行的呢?很显然,可以扫描 orders 表,检查每一条订单记录是否为已完成状态——注意,仅通过表 orders 即可找出所要信息似乎令人高兴,但实际情况并非如此,因为只有上述活动之后,才能检查最新状态的日期,即必须按照子查询编写的顺序来执行。
上述两个子查询是关联子查询,这很不好。因为必须要扫描 orders 表,这意味着我们必须检查 orders 的每条订单记录状态是否为 “COMPLETE”,虽然检查状态的子查询执行很快,但多次重复执行就不那么快了。而且,若第一个子查询没找到 “COMPLETE” 状态时,还必须执行第二个子查询。那么,何不试试非关联子查询呢?
要编写非关联子查询,最简单的办法是在第二个子查询上做文章。事实上,在某些 SQL 方言中,我们可以这么写:
and (o.ordid, os.statusdate) = (select ordid, max(statusdate) |
and (os.ordid, os.statusdate) = (select ordid, max(statusdate) |
前面已经看到了,非关联子查询可以变成内嵌视图,且改动不大。下面,我们写出“列出待办订单”的整个查询语句:
select c.custname, o.ordid, os.status, os.statusdate |
select c.custname, o.ordid, os.status, os.statusdate |
无法确定哪种方法一定更好,这一切都取决于实际数据。补充说明一点,最好别在预期会增大的表上做全表扫描操作(若能把搜索限制在最近一个月或几个月的数据上则会好些)。不过,最后一版的代码肯定比第一版的(在where子句用子查询)要好。
在结束“大数据量查询”的话题之前,有个特殊情况值得一提。当查询要返回非常大量的数据时,该查询很可能不是某个用户坐在电脑前敲入的命令,而是来自于某个批处理操作。即便“预备阶段”稍长,只要整个处理能达到令人满意的结果,就是可以接受的。当然,不要忘了,无论是不是预备阶段,都会需要资源——CPU、内存,可能还有临时磁盘空间。即使最基本的查询完全相同,优化器在返回大量数据时所选择的路径,仍可能会与返回少量数据时完全不同,了解这一点是有用的。
总结:尽早过滤掉不需要的数据。
| 回书目 上一节 下一节 |
|
||||
| · WCF开发基础 · 珊瑚虫QQ作者侵权案开庭 · SQL Server 2008/2005.. · 华为员工自杀频频拷问.. · 计算机网络维护入门 · 开源虚拟化技术Xen · 贝恩资本携手华为22亿.. · 如何优化IT 控制能耗 |
· VMware技术应用 · 打造安全服务器 · iSCSI应用与发展 · FTTx光纤接入 · Windows Server 2008专.. · Linux——从菜鸟到高手 · 微软出价446亿美元收购.. · RAID——磁盘阵列基础 |
|||
|
||||
| · iSCSI应用与发展 · SQL Server 2008/2005.. · SQL Server 2008/2005.. · iSCSI应用与发展 · RAID——磁盘阵列基础 · 中间件应用技术专题 · 深入了解PGP加密技术 · 病毒查杀专题 |
· 国际文档格式标准开战 · SSL VPN详细知识 · Linux防火墙 · 打造安全服务器 · Sniffer安全技术从入门.. · 木马原理与防范 · ADSL应用面面俱到 · 入侵防护系统(IPS)初探 |
|||
|
||||
| · iSCSI应用与发展 · 中间件应用技术专题 · SQL Server 2008/2005.. · iSCSI应用与发展 · RAID——磁盘阵列基础 · 身份认证技术 · 病毒查杀专题 · 清除流氓软件——51CTO.. |
· SSL VPN详细知识 · Sniffer安全技术从入门.. · 了解统一威胁管理(UTM).. · 网络钓鱼 · ADSL应用面面俱到 · ADSL应用面面俱到 · 木马原理与防范 · 反垃圾邮件技术应用 |
|||