虎虎漫画小说

繁体版 简体版
虎虎漫画小说 > > SQL语言艺术最新章节 > 第 6 章

第 6 章 免费阅读

据库能够处理来自不同用户的“资源争用(contention )”,并能在事务

(transaction)处理过程中遇到机器故障等极端情况下也保持数据一致xìng。当然,数据库还有

很多其他的功能,本书并未涵盖。

正如其名,结构化查询语言(Structured Query Language,SQL)无非是一种语言,虽然它与

数据库关系密切。将SQL语言和关系数据库等同视之,或者更糟——与关系理论等同视之,都

是错误的。这种错误就好比将掌握了电子表软件或文字处理软件视为掌握了“信息技术”。实际上,

有些软件产品并非数据库,但它们也支持SQL(注1)。另外, SQL在成为标准之前也不得不与

诸如RDO或QUEL等其他语言竞争,这些语言曾被许多理论家认为优于SQL。

为了解决所谓的“SQL问题”,你必须了解两个相关部分:SQL查询表达式和数据库优化器。如图

4-1所示,这两部分在三个不同区域里协同工作。图的中央是关系理论,这是数学家们尽情发挥

的区域。简而言之,关系理论支持我们通过一组关系运算符来搜寻满足某些条件的数据,这些

关系运算符几乎支持任何基本查询。关键在于,关系理论有严格的数学基础,我们完全可以相

信同一结果可由不同的关系表达式来获得,正如在算术中246/369完全等于2/3一样。

然而,尽管关系理论有至关重要的理论价值,但一些有重要实践意义的方面它并未涉及,这些

方面属于图中所示的“报告需求(reporting requircomnts)”的范围。其中最明显的例子就是结果

集的排序:关系理论只关心如何根据查询条件取得正确的数据集;而对我们这些实践者(而非

理论家)而言,关系cāo作阶段只负责准确无误地找出属于最终数据集的记录,而不同行的相同

字段的关系并不是在这个阶段处理,而是完全属于排序cāo作。另外,关系理论并不涉及各种统

计功能(例如百分位数等),而这些统计功能经常出现在不同的“SQL方言(dialect)”当中。关系

理论所研究的是集合(set),但并不涉及如何为这些集合排序。尽管有许多关于排序的数学理

论,但它们都与关系理论无关。

必须说明的是,关系cāo作与上述“报告需求”的不同在于关系cāo作适用于理论上无限大的、数学

意义上的集,无论是cāo作含有十行数据的表、一万行数据的表、还是一亿行数据的表,我们都

能以相同的方式对其施以任何过滤条件。再次强调:当我们只关心找出并返回符合查询条件的

数据时,关系理论是完全适用的;然而,当我们需要进行记录排序,或者执行一个大多数人错

误地认为它是关系cāo作的groupcāo作时,却已不再是针对可以无限大的数据集进行cāo作了,而必

须是一个有限数据集,于是这个结果数据集不再是数学意义上的“关系(relation)”了,至此我们

已经超出了关系cāo作层。当然,我们仍然可以利用SQL对该数据集进行一些有用的cāo作。

初步总结一下,我们可以将SQL查询表示为一个两层的cāo作,如图4-2所示。第一层是一个关系

cāo作的“核”,它负责找出我们要cāo作的数据集;第二层是“非关系cāo作层(non-relational layer)”,

它对有限的数据结果集进行“精雕细刻”从而产生用户期望的最终结果。

尽管图4-2简要地表达了SQL在数据处理环境中的位置,但SQL查询在大多数情况下都比这要复

杂得多,图4-2仅仅展示了一个总体的描述。关系cāo作中的过滤器(filter)有可能只是一个代名

词,其背后是几个独立过滤器的组合,例如通过union结构或子查询来实现;最终,SQL语句的

构成可以很复杂。稍后还会讨论编写SQL语句的问题,但我们接下来首先要讨论的是数据物理

实现和数据库优化器的关系。

总结:千万别把SQL查询的执行过程中真正的关系cāo作和附加的展现层(presentation layer)

功能混为一谈。

SQL

与优化器

SQL and the Optimizer

当SQL引擎处理查询时,会用优化器找出执行查询最高效的方式。此时关系理论又可以大有作

为了——优化器借助关系理论,对开发者提供的语义无误的原始查询进行有效的等价变换,即

使原始查询编写得相当笨拙。

优化是在数据处理真正被执行时发生的。经过变换的查询在执行时可能比语义上等效的其他查

询快得多,这因是否存在索引,以及变换与查询是否适应而不同。在第5章我们将介绍各种数据

存储模型;有时,特定存储模型决定了查询优化的方式。优化器会检查下列因素:定义了哪些

索引、数据的物理布局、可用内存大小,以及可用于执行查询任务的处理器数。优化器还很重

视查询直接或间接涉及的表和索引的数据量。最终,优化器根据数据库的实际实现情况对理论

上等价的不同优化方案做出权衡,产生有可能是最优的查询执行方案。

然而,要记住的关键一点是,尽管优化器在SQL查询的“非关系cāo作层”也偶有用途,但以关系

理论为支柱的优化器主要用于关系cāo作层。SQL查询的等价变换还提醒我们:SQL原本就是一

种声明xìng语言(declarative language)。换言之,SQL应该是用来表达“要做什么”、而非“如何来

做”的。理论上讲,从“要做什么”到“如何来做”的任务就是由优化器来完成的。

在第1章、第2章中讨论的SQL查询比较简单,但即使从编写技巧层面来说,拙劣的查询语句也

会影响优化器的效率。切记,关系理论的数学基础为数据处理提供了非常严谨的逻辑支持,因

此SQL艺术本应注重减小“非关系cāo作层”的厚度,即尽量在关系cāo作层完成大部分处理,否则

优化器在“非关系cāo作层”难以保证返回的结果数据和原始查询执行的结果一样。

另外,在执行非关系cāo作时(这里非关系cāo作不严格地定义为针对已知结果集的cāo作),应专注

于cāo作那些解决问题所必需的数据,不要画蛇添足。和当前记录不同,有限数据集必须以某种

方式进行临时存储(内存或硬盘),这会带来惊人的开销。随着结果集数据量的增大,这种开销

会急剧加大,尤其是在主存所剩无几的时候。主存不足会引发硬盘数据jiāo换等开销很高的活动。

而且,别忘了“索引所指的是硬盘地址,并非临时存储地址”,所以数据一旦进行临时存储,就意

味着我们向最快的数据访问方式说再见了(哈希方式可能例外)。

一些SQL方言会误导用户,使他们认为自己仍在关系世界中——但其实早就不是关系cāo作了。

举个简单的例子:不是经理的员工当中,哪五个人收入最高?这是个现实生活中很合理的问题,

但它包含了明显的非关系描述。“找出不是经理的员工”是其中的关系cāo作部分,由此获得一个有

限的员工集合,然后排序。有些SQL方言通过在select语句中增加特殊子句来限制返回的记录数,

很显然,排序和限制记录数都是非关系cāo作。其他SQL方言(这里主要是指Oracle)则采用另

外的机制,即用一个名为rownum的虚拟字段(dummy column)为查询结果编号——这意味着

编号工作发生在关系cāo作阶段。如果查询语句如下:

乍一看好像没问题,但输出结果却不符合要求,并没有返回不是经理的人中“收入最高的五位”,

而是返回不是经理的人中“最先被查到的五位”,以收入递减序返回。他们可能恰好是“收入最低

的五位”!(这是Oracle实践者都知道的陷阱,大家都中过招。)

现在分析一下上面的代码。查询的关系cāo作部分仅从employees表中,以完全不可知的顺序,

取出最先发现的五位非经理人员(只包含empncom和salary字段)。别忘了关系理论指出,关系

(以及描述关系的表)是无序的,关系中的元组(即记录)可以被存储或检索。上面的查询执

行后,收入最高的非经理人员或许在查询结果中,或许不在,无从知道查询结果是否满足查询

条件。

『加入书签,方便阅读』