SQL优化中,有一条放之四海而皆准的既定方针,那就是:永远以小数据驱动大数据。其本质其实就是以小的数据样本作为驱动查询能够优化查询效率,在SQL中,涉及到不同表数据的连接、转移、或者合并,这些操作必须得有个数据集作为“带头”大哥,即驱动数据,而这个驱动数据最好是数据量最小的那一个。

内大外小

在讨论数据库之前,日常开发中,我们经常会遇到数据样本数量不一致,但是需要进行检索的情况,比如某人在地铁的某节车厢里捡到N台Iphone,而车厢里正好有T个人,他应该怎么去检索双样本数据,从而找到失主?

for (int i = 0; i < N; i++)
for (int j = 0; j < T; j++)
find();

一般的说法是把循环次数少的循环放在外面,其实,这个问题的主要原因是CPU内部的指令执行机制。现在,基本上CPU内部都有分支指令预测,就是当执行(现在大多将这一阶段提前到预取指令时执行)到转移指令时,都会直接从分支目标缓存(BTB)中取出目标指令的地址,然后将要执行的指令提前预取到CPU的指令预取指令队列中。这样,显然大大提高了效率。一个N次的一层循环在执行时,除了在第一次和最后一次会预测错误外,其他N-i次都会预取成功,避免了执行转移指令时重新取出新指令造成的时间浪费。 所以,当有两层循环,外层循环数为N,内层为T,N远大于T,那么最终造成的预测错误数为N*2+2,而如果外层数为T,内层数为N,预测错误数为T*2+2,显然后者要节省更多时间,而且这个时间是很可观的。N比T越大,这个时间差越明显。

连表查询

回到数据库场景,连表查询操作本质上其实就是扫描驱动表数据,根据条件,逐一去大表找数据,由小表作为驱动表,小表数据少,那么去大表找数据时,能减少数据的找寻量。体现在底层上也就减少了网络的IO,内存,自然效率就高。

不同的连表方式也会有不同的驱动表,左连接中左边为驱动表,右边为被驱动表;右连接中右边为驱动表,左边为被驱动表;内连接中Mysql会选择数据量比较小的表作为驱动表,大表作为被驱动表。我们也可以通过EXPLANIN关键字查看SQL语句的执行计划,从而搞清楚一次连表查询中的驱动表到底是那一张。

底层原理

连表查询操作时,数据库会从头到尾扫描驱动表,复杂度为O(n),也就是说有N条就要查N次,随后再逐一去其它关联表查询数据,众所周知,由于Mysql采用B+tree方式进行存放数据,关于B+tree,请移步:霜皮剥落紫龙鳞,下里巴人再谈数据库SQL优化,索引(一级/二级/聚簇/非聚簇)原理,因此查询时间复杂度为O(logn),总时间复杂度即为O(n)*O(logn),说白了就是驱动数据集有多少条数据,就得在B+tree中查询O(logn)次。

假设表n数据小于表m,则连表查询操作时,O(n)*O(logm) 小于 O(m)*O(logn),因此小数据集作为驱动数据相对就比较有效率。

子查询

外小内大原则也同样适用于子查询,当子表的数据集较小时,使用In操作,效率较高:

SELECT * FROM A WHERE ID IN (SELECT ID FROM B)

这里B表的数据量小于A表数据,很明显B表作为查询筛选的驱动表。

反之,当B表数据量大于外侧的数据表A:

SELECT * FROM A WHERE  EXISTS (SELECT 1 FROM B WHERE B.ID = A.ID)

此时使用EXISTS的效率更高,因为EXISTS是将主查询的数据放到子查询中做条件验证,根据验证结果(TRUE或者FALSE)来决定主查询的数据结果是否能够得以保留。

结语

循环嵌套优化原则的外小内大,数据库SQL优化原则的以小博大,一脉相承,同出一辙,大道至简,殊途同归。

以小博大外小内大,Db数据库SQL优化之小数据驱动大数据的更多相关文章

  1. 数据库SQL优化大总结之 百万级数据库优化方案(转载)

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  2. 数据库sql优化总结之5--数据库SQL优化大总结

    数据库SQL优化大总结 小编最近几天一直未出新技术点,是因为小编在忙着总结整理数据库的一些优化方案,特此奉上,优化总结较多,建议分段去消化,一口吃不成pang(胖)纸 一.百万级数据库优化方案 1.对 ...

  3. 数据库SQL优化大总结之百万级数据库优化方案

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  4. (转)数据库SQL优化大总结之 百万级数据库优化方案

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  5. 数据库 SQL 优化大总结之:百万级数据库优化方案

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  6. 数据库SQL优化大总结之百万级数据库优化方案(转)

    add by zhj: 作者没有指定是哪个数据库,这只是一个近似通用的总结.对于某个特定的数据库,有些条目可能并不适用. 原文:http://www.cnblogs.com/yunfeifei/p/3 ...

  7. 【数据库】百万级数据库SQL优化大总结

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  8. 数据库SQL优化大总结之 百万级数据库优化方案(转)

    出处:http://www.cnblogs.com/yunfeifei/p/3850440.htm 网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不 ...

  9. 数据库SQL优化大总结之 百万级数据库优化方案 【转载】

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  10. 百万级数据库SQL优化大总结

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

随机推荐

  1. win10系统单独编译和使用WebRTC的回声消除(AEC)、音频增益(AGC)、去噪(NS)模块

    一.简介 本人想单独编译并使用WebRTC的音频回声消除模块,奈何技术有限,于是在百度的海洋里大海捞针,发现了https://www.cnblogs.com/mod109/p/5827918.html ...

  2. 使用 Kubernetes 简化平台工程

    平台工程在现代应用程序开发和部署中发挥的作用至关重要.随着软件应用程序变得越来越复杂和分散,对稳健且可扩展的基础设施的需求变得越来越重要.这就是平台工程的作用所在,它是支持整个软件开发生命周期的支柱. ...

  3. UVA10702 Travelling Salesman 题解

     UVA10702 Travelling Salesman 题解 题面: 有个旅行的商人,他每到一个的新城市,便卖掉所有东西再购买新东西,从而获得利润.从某城市 A 到某城市 B 有固定利润(B 到 ...

  4. 实验2_C语言分枝与循环基础应用编程

    试验任务1 task 1.c #include <stdio.h> #include <stdlib.h> #include <time.h> #define N ...

  5. 如何借助python第三方库存取不同应用程序的用户名、密码

    在之前的一系列文章中,小爬分享了很多用Pywin32.uiAutomation.sap Gui Script等技术实现应用程序或者Web网站(如SAP.Excel.outLook邮件系统.OA系统)的 ...

  6. gcd|最大公约数|欧几里得算法|欧几里得算法证明 一文说明白

    gcd 最大公因数,也称最大公约数.最大公因子,指两个或多个整数共有约数中最大的一个.a,b的最大公约数记为 $ gcd(a,b) $ ,同样的,a,b,c的最大公约数记为 $ gcd(a,b,c) ...

  7. 再见,Spring!你好,Solon!

    Solon 是什么框架? Java 生态级应用开发框架.从零开始构建,有自己的标准规范与开放生态(历时五年,具备全球第二级别的生态规模).与其他框架相比,解决了两个重要的痛点:启动慢,费内存. 解决痛 ...

  8. JUC并发编程学习笔记(九)阻塞队列

    阻塞队列 阻塞 队列 队列的特性:FIFO(fist inpupt fist output)先进先出 不得不阻塞的情况 什么情况下会使用阻塞队列:多线程并发处理.线程池 学会使用队列 添加.移除 四组 ...

  9. JavaScript 语法:语法约定与程序调试

    作者:WangMin 格言:努力做好自己喜欢的每一件事 JavaScript 语法约定 1.大小写的区分 1). JavaScript的关键字,永远都是小写的: 2). 内置对象,如Math和Date ...

  10. Ubuntu部署雷池Waf社区版

    安装docker环境 更新软件包 sudo apt update 安装docker环境 apt-get install docker.io docker -v 安装docker compose V2版 ...