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

上一篇文章《如何编写更好的SQL查询:终极指南-第一部分》中,我们学习了 SQL 查询是如何执行的以及在编写 SQL 查询语句时需要注意的地方。

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

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

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

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

  • 另一种是基于集合的方法,只需指定需要执行的操作。使用这种方法要做的事情就是,指定你想通过查询获得的结果的条件和要求。在检索数据过程中,你不需要关注实现查询的内部机制:数据库引擎会决定最佳的执行查询的算法和逻辑。

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

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

从查询到执行计划 

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

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

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

 

查询优化

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

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

  • 一些软件包功能工具可以生成查询计划的图形表示。

  • 其它工具能够为你提供查询计划的文本描述。

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

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

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

EXPLAINSELECT *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;
EXPLAINSELECT *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 ANALYZESELECT *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 ANALYZESELECT *FROM one_million JOIN half_millionON (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 ANALYZESELECT *FROM one_million JOIN half_millionON (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查询》系列的最后一篇文章,敬请期待。

相关文章:

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

  • Entity Framework Core 执行SQL语句和存储过程

  • SQL注入(SQL Injection)

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


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323751.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

POJ3349,洛谷SP4354-SnowflakeSnowSnowflakes【最小表示法,hash】

正题 洛谷评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidSP4354 POJ题目链接:http://poj.org/problem?id3349 题目大意 有n片雪花,他们6个角有不同的长度,如果两片雪花6个角长度相同(可以不同方向)&#…

publiccms实现遍历多级分类下的不同样式内容

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂 前言 现在是2022年1月2日17:06:51,假期这两天都在做publiccms。 上篇文章遗留的问题,最终还是没有按照富文本去做,后期在看吧; 今天遇到了个问题&…

四张图带你了解Tomcat系统架构--让面试官颤抖的Tomcat回答系列

转载自 四张图带你了解Tomcat系统架构--让面试官颤抖的Tomcat回答系列 俗话说,站在巨人的肩膀上看世界,一般学习的时候也是先总览一下整体,然后逐个部分个个击破,最后形成思路,了解具体细节,Tomcat的结构…

.NET Core 2.0应用程序大小减少50%

.NET Core 2.0应用程序减小体积瘦身官方工具 IL Linker。 IL Linker 来源于mono的linker https://github.com/mono/linker,目前还是预览版本。 在一般的情况下,链接器可以将应用程序的大小减少50%,大型应用程序的大小可能更有利…

P1368-工艺【最小表示法】

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP1368 题目大意 n个块,可以进行若干次将最左边的方块放在最右边,然后如果前面那个比后面那个瑕疵度小那么前面那个就是美丽的,求一个让最美丽的序列。 解题思路 求…

Orleans解决并发之痛(五):Web API

通过前面几篇文章的介绍,可能会疑问怎么在实际开发中调用Grain,之前Demo的Client都是基于控制台应用程序,实际开发下可能是基于Web Form、Web API、MVC......,由于一时短路了,没有联想到控制台应用程序的方式怎么切到其…

ASP.Net Core WebApi几种版本控制对比

一、版本控制的好处: (1)有助于及时推出功能, 而不会破坏现有系统。 (2)它还可以帮助为选定的客户提供额外的功能。 API 版本控制可以采用不同的方式进行控制,方法如下: (1&…

POJ2279-Mr. Young's Picture Permutations【线性dp】

正题 题目链接:http://poj.org/problem?id2279 题目大意 有k列,每列人数不同,要求从左到右和从前到后身高都单调递减,学生高度是1∼N1∼N(人数总和) 解题思路 我们开一个五维数组,然后每次在人少那列填充,按照这总…

JoyOI(TYVJ)1071-LCIS【线性dp,LIS,LCS】

正题 题目链接:http://www.joyoi.cn/problem/tyvj-1071 题目大意 求两个序列的最长公共上升子序列。 code 我们先回顾一下LIS和LCS LIS:fimax{fj1}(j<i,aj<ai)fimax{fj1}(j<i,aj<ai)LCS:fi,jmax⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪fi−1,jfi,j−1fi−1,j−11(a…

asp.net core策略授权

在《asp.net core认证与授权》中讲解了固定和自定义角色授权系统权限&#xff0c;其实我们还可以通过其他方式来授权&#xff0c;比如可以通过角色组&#xff0c;用户名&#xff0c;生日等&#xff0c;但这些主要取决于ClaimTypes&#xff0c;其实我们也可以自定义键值来授权&a…

Safari浏览器不支持let声明的解决方式

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年1月7日16:19:38,前几天用publiccms改了个网站&#xff0c;因为客户那边各种机型都有&#xff08;各PC端的分辨率也都不一样&#xff09;&#xff0c;所以导致页面呈现的效…

Executor 与 ExecutorService 和 Executors 傻傻分不清

转载自 Executor 与 ExecutorService 和 Executors 傻傻分不清 java.util.concurrent.Executor, java.util.concurrent.ExecutorService, java.util.concurrent. Executors 这三者均是 Java Executor 框架的一部分&#xff0c;用来提供线程池的功能。因为创建和管理线程非常心…

POJ3666-Making the Grade【线性dp】

正题 题目链接&#xff1a;http://poj.org/problem?id3666 题目大意 给定序列A,B。要求B严格单调&#xff0c;要求最小化 S∑Ni1|Ai−Bi|S∑Ni1|Ai−Bi|解题思路 根据书上说的数学归纳法&#xff0c;我们可以证明在S最小化的条件下&#xff0c;一定存在一种构造B的方案&am…

ASP.NET Core 2.0 自定义 _ViewStart 和 _ViewImports 的目录位置

在 ASP.NET Core 里扩展 Razor 查找视图目录不是什么新鲜和困难的事情&#xff0c;但 _ViewStart 和 _ViewImports 这2个视图比较特殊&#xff0c;如果想让 Razor 在我们指定的目录中查找它们&#xff0c;则需要耗费一点额外的精力。本文将提供一种方法做到这一点。注意&#x…

Safari浏览器不支持……

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂前言现在是2022年1月7日16:19:38,前几天用publiccms改了个网站&#xff0c;因为客户那边各种机型都有&#xff08;各PC端的分辨率也都不一样&#xff09;&#xff0c;所以导致页面呈现的效果…

json-lib的字符串自动转换坑

一、场景复现 &#xff08;1&#xff09;代码 import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.sf.json.JSONObject;public class C {public static void main(String…

JoyOI(TYVJ)1061-Mobile Service【线性dp】

正题 题目链接:http://www.joyoi.cn/problem/tyvj-1061 题目大意 有n个点&#xff0c;每个点之间都有权值不同的边&#xff0c;有3个机器人&#xff0c;有m个任务地点&#xff0c;机器人必须按顺序赶到任务地点&#xff0c;求最小代价。 解题思路 我们可以让fi,jfi,j表示两个…

开源分享 Unity3d客户端与C#分布式服务端游戏框架

很久之前&#xff0c;在博客园写了一篇文章&#xff0c;《分布式网游server的一些想法语言和平台的选择》&#xff0c;当时就有了用C#做网游服务端的想法。写了个Unity3d客户端分布式服务端框架&#xff0c;最近发布了1.0版本&#xff0c;取名ET框架。ET框架的目标就是简化客户…

freemarker中遇到null报错的处理方法

错误分析 今天遇到了这样的个问题&#xff0c;就是在获取分类的父id的时候发现如果是父级分类&#xff0c;则回去父id就会报错。 直接导致了后面的样式失败。 解决办法&#xff1a; 给添加了个默认值0&#xff0c;就可以了&#xff0c;代码如下&#xff1a; var cate_pare…

IDEA的debug方法头坑

一、现象复现 web程序跑起来很卡顿&#xff0c;十几分钟都跑步起来&#xff0c;而且页面刷新十几秒都没有反应。 三月 23, 2019 11:58:22 上午 com.mchange.v2.log.MLog <clinit> 信息: MLog clients using java 1.4 standard logging. 三月 23, 2019 11:58:22 上午 co…