如何编写更好的SQL查询:终极指南-第二部分

上一篇文章中,我们学习了 SQL 查询是如何执行的以及在编写 SQL 查询语句时需要注意的地方。

下面,我进一步学习查询方法以及查询优化。

 

基于集合和程序的方法进行查询

反向模型中隐含的事实是,建立查询时基于集合和程序的方法之间存在着不同。

  • 查询的程序方法是一种非常类似于编程的方法:你告诉系统需要做些什么以及如何做。例如上一篇文章中的示例,通过执行一个函数然后调用另一个函数来查询数据库,或者使用包含循环、条件和用户定义函数(UDF)的逻辑方式来获得最终查询结果。你会发现通过这种方式,一直在请求一层一层中数据的子集。这种方法也经常被称为逐步或逐行查询。
  • 另一种是基于集合的方法,只需指定需要执行的操作。使用这种方法要做的事情就是,指定你想通过查询获得的结果的条件和要求。在检索数据过程中,你不需要关注实现查询的内部机制:数据库引擎会决定最佳的执行查询的算法和逻辑。

由于 SQL 是基于集合的,所以这种方法比起程序方法更加有效,这也解释了为什么在某些情况下,SQL 可以比代码工作地更快。

基于集合的查询方法也是数据挖掘分析行业要求你必须掌握的技能!因为你需要熟练的在这两种方法之间进行切换。如果你发现自己的查询中存在程序查询,则应该考虑是否需要重写这部分。

 

从查询到执行计划 

反向模式不是静止不变的。在你成为 SQL 开发者的过程中,避免查询反向模型和重写查询可能会是一个很艰难的任务。所以时常需要使用工具以一种更加结构化的方法来优化你的查询。

对性能的思考不仅需要更结构化的方法,还需要更深入的方法。

然而,这种结构化和深入的方法主要是基于查询计划的。查询计划首先被解析为“解析树”并且准确定义了每个操作使用什么算法以及如何协调操作过程。

 

查询优化

在优化查询时,很可能需要手动检查优化器生成的计划。在这种情况下,将需要通过查看查询计划来再次分析你的查询。

要掌握这样的查询计划,你需要使用一些数据库管理系统提供给你的工具。你可以使用以下的一些工具:

  • 一些软件包功能工具可以生成查询计划的图形表示。
  • 其它工具能够为你提供查询计划的文本描述。

请注意,如果你正在使用 PostgreSQL,则可以区分不同的 EXPLAIN,你只需获取描述,说明 planner 如何在不运行计划的情况下执行查询。同时 EXPLAIN ANALYZE 会执行查询,并返回给你一个评估查询计划与实际查询计划的分析报告。一般来说,实际执行计划会切实的执行这个计划,而评估执行计划可以在不执行查询的情况下,解决这个问题。在逻辑上,实际执行计划更为有用,因为它包含了执行查询时,实际发生的其它细节和统计信息。

接下来你将了解 XPLAIN 和 ANALYZE 的更多信息,以及如何使用这两个命令来进一步了解你的查询计划和查询性能。要做到这一点,你需要开始使用两个表: one_million 和 half_million 来做一些示例。

你可以借助 EXPLAIN 来检索 one_million 表的当前信息:确保已将其放在运行查询的首要位置,在运行完成之后,会返回到查询计划中:

EXPLAIN
SELECT *
FROM one_million;
QUERY PLAN
_________________________________________________
Seq Scan on one_million
(cost=0.00..18584.82 rows=1025082 width=36)
(1 row)

在以上示例中,我们看到查询的 Cost 是0.00..18584.82 ,行数是1025082,列宽是36。

同时,也可以借助 ANALYZE 来更新统计信息  。

ANALYZE one_million;
EXPLAIN
SELECT *
FROM one_million;
QUERY PLAN_________________________________________________
Seq Scan on one_million
(cost=0.00..18334.00 rows=1000000 width=37)
(1 row)

除了 EXPLAIN 和 ANALYZE,你也可以借助 EXPLAIN ANALYZE 来检索实际执行时间:

EXPLAIN ANALYZE
SELECT *
FROM one_million;
QUERY PLAN
___________________________________________________
Seq Scan on one_million
(cost=0.00..18334.00 rows=1000000 width=37)
(actual time=0.015..1207.019 rows=1000000 loops=1)
Total runtime: 2320.146 ms
(2 rows)

使用 EXPLAIN ANALYZE 的缺点就是需要实际执行查询,这点值得注意!

到目前为止,我们看到的所有算法是顺序扫描或全表扫描:这是一种在数据库上进行扫描的方法,扫描的表的每一行都是以顺序(串行)的顺序进行读取,每一列都会检查是否符合条件。在性能方面,顺序扫描不是最佳的执行计划,因为需要扫描整个表。但是如果使用慢磁盘,顺序读取也会很快。

还有一些其它算法的示例:

EXPLAIN ANALYZE
SELECT *
FROM one_million JOIN half_million
ON (one_million.counter=half_million.counter);
QUERY PLAN
_____________________________________________________________
Hash Join (cost=15417.00..68831.00 rows=500000 width=42)
(actual time=1241.471..5912.553 rows=500000 loops=1)
Hash Cond: (one_million.counter = half_million.counter)
    -> Seq Scan on one_million
    (cost=0.00..18334.00 rows=1000000 width=37)
    (actual time=0.007..1254.027 rows=1000000 loops=1)
    -> Hash (cost=7213.00..7213.00 rows=500000 width=5)
    (actual time=1241.251..1241.251 rows=500000 loops=1)
    Buckets: 4096 Batches: 16 Memory Usage: 770kB
    -> Seq Scan on half_million
    (cost=0.00..7213.00 rows=500000 width=5)
(actual time=0.008..601.128 rows=500000 loops=1)
Total runtime: 6468.337 ms

我们可以看到查询优化器选择了 Hash Join。请记住这个操作,因为我们需要使用这个来评估查询的时间复杂度。我们注意到了上面示例中没有 half_million.counter 索引,我们可以在下面示例中添加索引  :

CREATE INDEX ON half_million(counter);
EXPLAIN ANALYZE
SELECT *
FROM one_million JOIN half_million
ON (one_million.counter=half_million.counter);
QUERY PLAN
______________________________________________________________
Merge Join (cost=4.12..37650.65 rows=500000 width=42)
(actual time=0.033..3272.940 rows=500000 loops=1)
Merge Cond: (one_million.counter = half_million.counter)
    -> Index Scan using one_million_counter_idx on one_million
    (cost=0.00..32129.34 rows=1000000 width=37)
    (actual time=0.011..694.466 rows=500001 loops=1)
    -> Index Scan using half_million_counter_idx on half_million
    (cost=0.00..14120.29 rows=500000 width=5)
(actual time=0.010..683.674 rows=500000 loops=1)
Total runtime: 3833.310 ms
(5 rows)

通过创建索引,查询优化器已经决定了索引扫描时,如何查找 Merge join。

请注意,索引扫描和全表扫描(顺序扫描)之间的区别:后者(也称为“表扫描”)是通过扫描所有数据或索引所有页面来查找到适合的结果,而前者只扫描表中的每一行。

 

教程的第二部分内容,就介绍到这里。后续还会有《如何编写更好的SQL查询》系列的最后一篇文章,敬请期待。

原文链接:http://www.kdnuggets.com/2017/08/write-better-sql-queries-definitive-guide-part-2.html

转载请注明出自:葡萄城控件

 

相关阅读:

【报表福利大放送】100余套报表模板免费下载

如何编写更好的SQL查询:终极指南-第一部分

一句SQL完成动态分级查询

迁移 SQL Server 数据库到 Azure SQL 实战

 

时间: 2024-08-02 20:42:31

如何编写更好的SQL查询:终极指南-第二部分的相关文章

如何编写更好的SQL查询:终极指南-第三部分

本次我们学习<如何编写更好的SQL查询>系列的最后一篇文章.   时间复杂度和大O符号 通过前两篇文章,我们已经对查询计划有了一定了解.接下来,我们还可以借助计算复杂度理论,来进一步深入地挖掘和思考性能的提升.理论计算机科学这一领域聚焦于:根据难度来对计算问题进行分类.这些计算问题可以是算法问题,也可以是查询问题. 对于查询,我们可以不按照难度进行分类,而是按照运行查询并得到结果所需的时间来进行分类.这种方式也被称为按照时间复杂度进行分类. 使用大O符号,可以根据输入的增长速度来表示运行时间,

如何编写更好的SQL查询:终极指南-第一部分

结构化查询语言(SQL)是数据挖掘分析行业不可或缺的一项技能,总的来说,学习这个技能是比较容易的.对于SQL来说,编写查询语句只是第一步,确保查询语句高效并且适合于你的数据库操作工作,才是最重要的.这个教程将会提供给你一些步骤,来评估你的查询语句. 首先,应该了解学习SQL对于数据挖掘分析这个工作的重要性; 接下来,应该学习SQL查询语句的处理和执行过程,以便可以更好的了解到,编写高质量的查询有多重要.具体说来就是,应该了解查询语句是如何被解析.重写.优化和最终评估的; 掌握了上面一点之后,你不

如何编写更好的SQL查询:终极指南(上)

结构化查询语言(SQL)是数据挖掘分析行业不可或缺的一项技能,总的来说,学习这个技能是比较容易的.对于SQL来说,编写查询语句只是第一步,确保查询语句高效并且适合于你的数据库操作工作,才是最重要的.这个教程将会提供给你一些步骤,来评估你的查询语句. 首先,应该了解学习SQL对于数据挖掘分析这个工作的重要性; 接下来,应该先学习SQL查询语句的处理和执行过程,以便可以更好的了解到,编写高质量的查询有多重要.具体说来就是,应该了解查询是如何被解析.重写.优化和最终评估的; 掌握了上面一点之后,你不仅

使用正规表达式编写更好的 SQL

Oracle Database 10g 中的正规表达式特性是一个用于处理文本数据的强大工具 Oracle Database 10g 的一个新特性大大提高了您搜索和处理字符数据的能力.这个特性就是正规表达式,是一种用来描述文本模式的表示方法.很久以来它已在许多编程语言和大量 UNIX 实用工具中出现过了. Oracle 的正规表达式的实施是以各种 SQL 函数和一个 WHERE 子句操作符的形式出现的.如果您不熟悉正规表达式,那么这篇文章可以让您了解一下这种新的极其强大然而表面上有点神秘的功能.已

菜鸟小弟单位任务到了最后关头,深夜编写代码受阻求助SQL查询字符串问题(VS2003,VB.NET)

问题描述 请问以下的代码有什么问题?又是本菜鸟头疼的查询字符串问题,希望各位大哥大姐帮我看看.该代码实现将DATAGRID的数据源DATATABLE中的数据写回到数据库,可是要做数值的转换和连接字符串时候的连接符号.单双引号,把我蒙住了,由于水平差,已经通宵2天了,又要去上班,苦啊!运行时候系统报错,说是什么数目不同,无法插入数据系统(VS2003,语言是VB.NET,数据库是SQL2005EXPRESS)小弟分数不多了,全部送上!!'++++++++++++++++++++++++++++++

使用SQL查询DB2 9中的XML数据

虽然 DB2 的混合体系结构与之前的版本有很大的不同,但是要利用它的新 XML 功能并不难.如果您已经熟悉 SQL,那么很快就可以将这方面的技能转化到对存储在 DB2 中的本地 XML 数据的处理上.通过本文就可以知道如何实现这一点. DB2 Viper(就是DB2 9)中的 XML 特性包括新的存储管理.新的索引技术以及对查询语言的支持.在本文中,学习如何使用 SQL 或带 XML 扩展的 SQL(SQL/XML)查询 DB2 XML 列中的数据.接下来的文章将讨论 DB2 中新引入的对新兴的

使用SQL查询DB2 9中的XML数据_DB2

正在看的db2教程是:使用SQL查询DB2 9中的XML数据. 虽然 DB2 的混合体系结构与之前的版本有很大的不同,但是要利用它的新 XML 功能并不难.如果您已经熟悉 SQL,那么很快就可以将这方面的技能转化到对存储在 DB2 中的本地 XML 数据的处理上.通过本文就可以知道如何实现这一点. DB2 Viper(就是DB2 9)中的 XML 特性包括新的存储管理.新的索引技术以及对查询语言的支持.在本文中,学习如何使用 SQL 或带 XML 扩展的 SQL(SQL/XML)查询 DB2 X

必须知道的SQL编写技巧,多条件查询不拼字符串的写法

原文:必须知道的SQL编写技巧,多条件查询不拼字符串的写法 在做项目中,我们经常遇到复杂的查询方法,要根据用户的输入,判断某个参数是否合法,合法的话才能当作过滤条件,我们通常的做法是把查询SQL赋值给一个字符串变量,然后根据判断条件动态的拼接where条件进行查询.下面来简单说一下写SQL中遇到的问题和解决办法.   一.不确定字段名,而产生的SQL字符串拼接                                                                    

编写SQL查询来查找IBM DB2 for Linux和Windows数据库中的外键关系

当一个数据库中存在大量外键约束时,您可能发现难以可视化表之间的外键关系.本文将探讨如何编写 SQL 查询来查找 DB2 for Linux, UNIX, and Windows 中的外键关系. 文中将讨论以下变体. 给定一个外键父表,返回 RI(参照 完整性)子表和后代表,以及从附表到这些子表和后代表的 RI 关系路径. 修改所提供的查询,以返回数据库中所有表的结果. 样例模式 清单 1 中所示的样例模式将用于本文中的示例. 清单 1. 样例模式 set schema newton; creat