首页 > 数据库 >以小博大外小内大,Db数据库SQL优化之小数据驱动大数据

以小博大外小内大,Db数据库SQL优化之小数据驱动大数据

时间:2022-12-24 14:57:37浏览次数:68  
标签:外小内 以小 Db 查询 连表 指令 SQL 驱动 数据

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,驱动,数据
From: https://www.cnblogs.com/v3ucn/p/16994717.html

相关文章

  • SRE从CMDB到SMDB的自动化探索演进——面向服务的运维
    SRE和系统运维的最大区别,我认为SRE得在系统运维的基础上研究业务,研究系统架构、产品架构,SRE面向的是用户稳定性。大型互联网系统,模块多、依赖关系和运行环境复杂,如果不了解......
  • lightdb extra_float_digits--控制浮点数精度
    建一张表,两个字段类型分别是float和numeric,然后插入数据,如下:zjh@postgres=>createtablet1(c1float,c2numeric);CREATETABLEzjh@postgres=>insertintot1values(0.555......
  • lightdb数据库链接之postgresql_fdw
    FDW简介FDW(ForeignDataWrapper)是lightdb的一个插件。通过FDW,可以将远程pg数据库映射到本地(映射为server),将远程数据库table映射为本地的foreigntable。通过FDW映......
  • LinkedBlockingQueue
    ​​https://www.jianshu.com/p/cc2281b1a6bc​​​继承关系图    /***节点类,用于存储数据*/staticclassNode<E>{Eitem;Node<E>ne......
  • 实现multbandblend
    一、首先实现laplacian金字塔的分割和重构#include "stdafx.h"#include <iostream>#include <vector>#include <opencv2/c......
  • MongoDB 索引原理与索引优化
    转载请注明出处:1.MongoDB索引索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种......
  • Wallys/IPQ4018 12V-56VDCPassive 24V-56V/2*MMCX 27dbm Support MU-MIMO /industrial
    MT7915/MT7975/IPQ6000/IPQ6018/IPQ6010/IPQ4019/IPQ4029/ipq4018/IPQ4028/IPQ8072/IPQ8072A/IPQ8074/IPQ8074A/IPQ9074/QCN9074/QCN9072/QCN9024/IPQ5018/AR9223/QCA9880/......
  • python中用ibm_db连接远程数据库出现SQLSTATE=58004 错误的解决方法。
    官方抄了个例子importibm_dbibm_db.connect("DATABASE=name;HOSTNAME=host;PORT=60000;PROTOCOL=TCPIP;UID=username;PWD=password;","","")连接本地数据库没问......
  • 使用 REST 访问 MongoDB 数据
    本指南将引导您完成创建应用程序的过程,该应用程序通过基于超媒体休息的前端。您将构建什么您将构建一个Spring应用程序,该应用程序允许您创建和检索存储在​​Person​​蒙......
  • MariaDB 公司正式在纽交所上市
    MariaDB公司正式在纽交所上市来源:OSCHINA编辑: 局2022-12-2215:54:45 9今年2月,开源数据库MariaDB公司完成了 1.04亿美元的D轮融资,并表示计划......