阅读更多

0顶
0踩

数据库

原创新闻 如何最有效的编写SQL

2017-07-11 16:05 by 副主编 jihong10102006 评论(0) 有12056人浏览
sql
引用
原文:The Most Effective Way to Write Effective SQL: Change Your Thinking Style
作者: Emrah Mete
翻译:黑色巧克力

译者注:解决数据库级(SQL)工作上的问题,应该采用的是SET方法(整体的)而不是过程式的方法。下面来看看作者为什么这么说。

编写有效的SQL查询是企业软件世界中最大的难题之一。

每个公司在数据库开发项目中所面临的最根本的问题,在于开发环境中实现的性能不能在生产环境中实现。一般来说,存在性能损失是因为生产环境中的数据量要大得多。

这些问题(运行缓慢的数据库操作)可能有各种各样的原因。本文将解释如何在编写查询时进行思考,如何思考是最基本的问题,也是解决此类问题的起点。

观察发现SQL开发人员常使用过程方法编写查询。事实上,这是很自然的,因为用程序方法解决问题是最方便的人类逻辑解决方案。另一个方面,几乎所有的SQL开发人员都在同时编写Java、c#或其他编程语言的代码。Java、C#等可以用来训练开发人员以一种程序化的方式来培养他们的思维方式,因为当使用这些语言开发应用程序时,会使用很多类似的东西,比如IF .. THEN .. ELSE,FOR .. LOOP,WHILE .. DO, CASE .. WHEN。当然,在这种情况下,当将业务规则应用到一组数据时,意味着每个记录都是单独处理的(逐行处理)。这个过程方法在Java、c#等语言中使用。虽然使用语言开发软件是一种正确的方法,但在编写数据库级(SQL)的查询时,却不会产生同样的效果。

下面用两种不同的方法来解决同一个示例问题,并将结果进行比较。看看CUSTOMERS表中对应的每个客户在SALES表中有多少条记录。

过程式方法如下:
SET AUTOTRACE ON
SELECT 
      c.cust_id,
       (SELECT COUNT (*)
          FROM sh.sales s
         WHERE s.cust_id = c.cust_id)
          sa_count
  FROM SH.CUSTOMERS c;
Plan hash value: 881374884
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
    2454756  consistent gets
          0  physical reads
          0  redo size
     925474  bytes sent via SQL*Net to client
      41104  bytes received via SQL*Net from client
       3701  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      55500  rows processed


现在,采用基于SET的方法来编写查询。
SET AUTOTRACE ON
SELECT 
        c.cust_id, COUNT (s.cust_id) jh_count
    FROM SH.CUSTOMERS c, sh.sales s
   WHERE c.cust_id = s.cust_id(+)
GROUP BY c.cust_id;
Plan hash value: 716053480
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        742  consistent gets
          0  physical reads
          0  redo size
     925474  bytes sent via SQL*Net to client
      41104  bytes received via SQL*Net from client
       3701  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      55500  rows processed


可以看到在两个查询的consistent gets数量之间的差异(当检查缓冲区缓存读到的块数据时)是巨大的。使用两种不同方法编写的查询在运行时导致不同时间。这种差别可以用性能来解释。

在另一个例子中,常见的习惯是在SQL语句中调用PL/SQL函数。作为过程式工作的例子,也是一种解决问题的方法。还有其他一些影响在SQL内调用PL/SQL代码性能的不利因素,但在本文中,不会提到性能问题。

下面编写查找客户表中每个客户的购买金额的代码。

过程方法:

在第一步中,创建一个PL/SQL函数来计算每个客户的总数,然后在代码和输出中调用这个函数。
CREATE OR REPLACE FUNCTION get_grand_total (
   p_cust_id_in IN SH.CUSTOMERS.CUST_ID%TYPE)
   RETURN NUMBER
IS
   r_grand_total   NUMBER;
BEGIN
   SELECT SUM (amount_sold)
     INTO r_grand_total
     FROM sh.sales
    WHERE cust_id = p_cust_id_in;
   RETURN r_grand_total;
END;
SET AUTOTRACE ON
SELECT cust_id, 
            get_grand_total (cust_id) grand_total 
FROM sh.customers;
Statistics
----------------------------------------------------------
      55503  recursive calls
          0  db block gets
    3066293  consistent gets
          0  physical reads
          0  redo size
     890447  bytes sent via SQL*Net to client
      41104  bytes received via SQL*Net from client
       3701  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      55500  rows processed



现在,采用基于SET的方法来编写查询。
SET AUTOTRACE ON
  SELECT c.cust_id, SUM (amount_sold)
    FROM SH.CUSTOMERS c, sh.sales s
   WHERE c.cust_id = s.cust_id(+)
GROUP BY c.cust_id;
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1841  consistent gets
          0  physical reads
          0  redo size
     890452  bytes sent via SQL*Net to client
      41104  bytes received via SQL*Net from client
       3701  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      55500  rows processed


在本例中,通过查看consistent GETS和递归调用输出,我们可以看到相同的情况。

我们的查询也是生成更高效的数据库操作的第一步,它考虑的是批处理,而不是逐行思考。在进行数据库操作时,批处理的方法会让你在一天结束时消耗更少的资源,从而提高工作效率。
  • 大小: 112.9 KB
  • 大小: 55.6 KB
  • 大小: 47.9 KB
  • 大小: 57.5 KB
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Java 转 C++ 知识点

    分为data段(已初始化)和bss段(未初始化) 5)文字常量区:程序结束后由系统释放,存放常量字符串 6)text 程序代码区:存放函数体的二进制代码 与Java相比: c++的heap需要程序员手动分配和释放 C++的堆和栈都...

  • MFC Windows应用程序设计

    MFC Windows应用程序设计 一二三章

  • Java, C++同时实现SocketServer功能 程序比较

    前面已经写了Java, C++同时实现SocketClient功能 程序比较,比较了java,c++写TcpClient程序的不同,今天比较TcpServer程序的不同 分别用java,C++写了2个程序,程序实现功能相同,都是socket服务器通信,主要的...

  • C#与C++、Java之比较概览

    C#与C++、Java之比较概览 Ben Albahari 著 荣耀 译 本文翻译时间较早。欢迎指出任何误失。谢谢。 感谢以下人士的支持和反馈(按字母先后顺序): Don Box、C.R. Manning、Joe Nalewabau、John Osborn、Thomas ...

  • C/C++超级大火锅

    多数是c/c++,也有少量java基础和其他知识,貌似应该叫《计算机基础问题汇总》比较好。不断更新~~一、new 跟 malloc 的区别是什么?1.malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符2.new能够自动...

  • 360、腾讯、迅雷Windows编程、网络编程面试题及答案

    4)显示ShowWindow&更新窗口UpdateWindowà4)循环获取消息GetMessage(){翻译(转换)TranslateMessage消息、处理消息DispathMessage(将消息交付给窗口过程进行处理)}。2,线程:相对与进程而言,线程是一个更加...

  • Java最全八股文(2023最新整理)

    Java面试八股文

  • 软件设计师-JAVA程序设计语言

    Java语言简介: 背景 1991年 ,SUN MicroSystem公司的 Jame Gosling、 Bill Joe等人 ,在电 视、控制烤面包箱等家用消费类电子产品上进行交互式操作的开发,开始时是使用C++语言,但是,后来发现C++在某些方面并不能...

  • C/C++面试宝典2024版(最新版)

    面试基础前言new、delete、malloc、free关系delete与 delete []区别C和C++ 的共同点?不同之处?继承的优缺点C++有哪些性质(面向对象特点)子类析构时要调用父类的析构函数吗?多态,虚函数,纯虚函数求下面函数的...

  • 【笑小枫-面试篇】Java基础面试题整理,努力做全网最全

    Java基础知识面试题整理,你需要的这里都有,赶快点赞收藏,需要的时候看看哟!

  • 高级Java程序面试问题整理

    文章目录Java基础基本数据类型float和double区别Object 常见方法Java中数据结构Java中异常处理访问控制修饰符== 与 equals区别重写equals方法,为什么要重写hashcodefinal 关键字的一些总结String 和 StringBuffer、...

  • KafKa C++实战

    1. Kafka架构是由producer(消息生产者)、consumer(消息消费者)、borker(kafka集群的 server,负责处理消息读、写请求,存储消息,在kafka cluster这一层这里,其实里面是有很多个 broker)、topic(消息队列/分类...

  • activeMQ消息中间件原理以及java代码实现

    在介绍activeMQ之前我们先来了解下什么是消息中间件,在客户端和服务器之间进行通讯时,客户发送请求后,服务器必须正确处理完成后才能继续执行以后的步骤,而且如果服务器涉及到异常错误或者网络故障以及服务对象...

  • 后端开发、C++开发面经分类整理

    博主秋招参加了字节百度腾讯B站虾皮美团等多个大厂的秋招,均已得到offer。...我投递的主要是后端开发工程师、C++开发等,感觉遇到的问题大致可以归纳为以下几类:存储 语言 操作系统 网络 分布式 数据结构 和其他

  • java毕业设计——基于java+java-swing的泡泡堂网络游戏设计与实现(毕业论文+程序源码)——泡泡堂网络游戏

    安全性 Java的编程类似C++,但舍弃了C++的指针对存储器地址的直接操作,程序运行时,内存由操作系统分配,这样可以避免病毒通过指针入侵系统。它提供了安全管理器,防止程序的非法访问。 面向对象 Java吸收了C++面向...

  • Socket网络编程之组播实现(C++,Rust)

    一、C++实现(Windows) 服务端源码 服务端需要添加加入组播组的相关代码。 #include "stdafx.h" #include<WinSock2.h> #include<Ws2tcpip.h> //ip_mreq头文件 #include<iostream> using ...

  • C++网络编程

    UDP是面向无连接的,双方建立的是数据报套接字,服务器和客户端在进行传描数据之前不需要进行连接的申请和建立,可以随时向对方发消息。 TCP 优点:可靠、稳定 缺点:速度慢,效率低、占用系统资源高、易被攻击。 ...

  • 2022Java基础、语法最全面试题,为秋招做好准备

    1.Java跨平台原理(字节码文件、虚拟机)C/C++语言都直接编译成针对特定平台机器码。如果要跨平台,需要使用相应的编译器重新编译。Java源程序(.java)要先编译成与平台无关的字节码文件(.class),然后字节码文件再...

  • JAVA确保垃圾回收后结束程序_Java内存垃圾回收机制(转贴)

    Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通 过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。一般来说,堆的是由垃 圾回收 来负责的...

  • java笔记 自己用

    java基础知识总结,参考: https://www.cnblogs.com/schiller-hu/p/10662429.html 或 https://www.cnblogs.com/jacking0325/p/10859350.html (通俗易懂) 继承: 好处: 1.减少代码的冗余性 2.提高代码的复用性 3...

Global site tag (gtag.js) - Google Analytics