设为首页 收藏本站
查看: 887|回复: 0

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

[复制链接]

尚未签到

发表于 2018-10-20 07:04:05 | 显示全部楼层 |阅读模式

  上一篇文章中,我们学习了 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>  (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>  (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>  (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>  (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>  (actual time=0.007..1254.027 rows=1000000 loops=1)

  -> Hash (cost=7213.00..7213.00 rows=500000>  (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>  (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>  (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>  (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>  (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
  转载请注明出自:葡萄城控件



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-623801-1-1.html 上篇帖子: 史上最全最正确的zabbix server安装过程 下篇帖子: open***-server 搭建
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表