數據庫性能系列之子查詢

前言

16150c9aa797df4d8cc4176dc9a5fd78.png

說起數據庫,想必一些朋友會認為,數據庫不就是天天CRUD嗎?只要我掌握了這幾招,根本不在話下。是的,其實我也很贊同這個觀點,對于大多數應用程序來說,只掌握這些內容,是可以勝任日常的開發工作的。

然而我們的程序不可能始終停留在測試環境,隨著生產環境數據量的增大,以及用戶規模的增長,數據庫就會出現一些性能方面的問題。所以接下來的一段時間內,我們會學習一些數據庫性能優化方面的內容,希望可以帶給大家一些啟迪和成長。今天,我們就從最基本的子查詢講起。

概述

ee6e0a3d0834f72c84a35fea4eb16288.png

子查詢的定義本身很簡單,就是一種嵌套查詢。最常見的例子就是我們有兩張表students和classes,為了簡化說明,此處沒有遵守三大范式,表中的字段如下:

sutdents

id
stu_namestu_ageclass_id
1
張三
15
1002
2李四
15
1001
3王五
16
1002
4朱六14
1003

classes

class_id
class_name
1001
語文
1002
數學
1003英語

此時我們想查詢哪些學生選擇了數學課,就可以使用子查詢去查找結果:

SELECT stu_name FROM sutdents WHERE sutdents.class_id IN (SELECT class_id FROM classes WHERE class_name = '數學')

可以看出,我們在這里使用了IN操作符來關聯子查詢的結果,熟悉的伙伴一定清楚,還有一種子查詢的方式叫做EXISTS,使用方式如下:

SELECT stu_name FROM sutdents s  WHERE EXISTS (SELECT 1 FROM classes c WHERE s.class_id = c.class_id AND class_name = '數學')

兩種方式的查詢結果都是一致的,我們找出了哪些學生選擇了數學課:

5458908591455ea49c9fe5ca88a5f393.png

但實際上,這兩種子查詢的效率在不同的情況下是不一樣的,下面我們來單獨談談這兩種方式的區別。

什么是IN

6fb888eb70bebb5b56fe70ad5b4e37d5.png

從字面意思來看,IN即為外部表的字段,使用內部嵌套查詢的結果中作為條件去查詢所需的結果。因此,使用IN時,內部嵌套的子查詢只會查詢一次,這里引申出一個概念,叫做:非關聯子查詢。

在我們上述的示例中,子查詢會先從classes表中找出課程名稱為“數學”的id,此時子查詢只執行了一次。通過查詢的結果,即數學課的id號,作為外部查詢的條件,去查找最終的結果。

什么是EXISTS

cbd533c5f767d8b1384a2563768849e3.png

同樣的,顧名思義,EXISTS即為“存在”。也就是說,在嵌套查詢時,外部表的信息,需要在內部表的結果中存在,才可以查詢出結果。因此,使用EXISTS時,內部嵌套的子查詢會查詢多次,次數取決于外部表的記錄條目,最終返回對應的結果給外部表,這個概念叫做:關聯子查詢。

在上述示例中,查詢語句會先從students表中找出每一條記錄對應的class_id,然后傳遞給內部的子查詢,內部子查詢使用該class_id進行匹配,去classes表中查找滿足class_id和class_name為“數學”的記錄,再返回給外部的表。在此過程中,只有完全匹配的記錄,才會呈現最終的結果。

如何優化子查詢

beca99fcde67ebbb776b173e0ca62617.png

在以往的很多經驗和一些文章中經常會提到,優化SQL語句,需要使用EXISTS來代替IN,即可達到效果。那么這句話究竟是不是正確的呢?

通過今天的學習,我們現在已經知道,這句話不完全正確,也不完全錯誤。究其根因,我們已經了解了IN和EXISTS的特性,所以結論如下:

1、如果一個語句中,子查詢外部的表A,數量小于子查詢內部的表B,那么此時,使用EXISTS的效率,是要大于IN的。這是因為EXISTS每次查詢會循環表A中的數據,然后傳入表B進行匹配,此種情況下,使用EXISTS循環次數少,需要查詢的記錄條目也更少。

2、反之,如果子查詢外部的表A,數量大于子查詢內部的表B,那么此時,使用IN的效率會更高。此時使用IN可以縮小要查找的記錄范圍,最終匹配表A時可以減少記錄的大小。

總結

be06a1ac41ee1d320bd3110c58f5fb9b.png

今天我們闡述了子查詢的概念和一些簡單的用法,以及一些優化方式。我們可以將子查詢分為關聯子查詢和非關聯子查詢兩種模式,分別對應IN和EXISTS的用法。最后我們在優化子查詢時提到了使用哪種方式取決于外表和內表的大小關系,其實優化的重心在于使用小表來驅動大表的原則,這些你都學會了嗎?

下一期我們會從數據庫索引的角度來繼續講述數據庫性能優化的方式,朋友們,我們下期再見!

9dc334ca83a6ef38fb4cd79140608110.png

您的點贊和在看是我創作的最大動力,感謝支持

ea7d615b81970e0db97f9beb5cd0d8e8.jpeg

cc4a1e4bc96ad0f9e025d9163a6dbac5.png

e0d15d7d4ddbe53a51fbadf656f87ab6.png

公眾號:wacky的碎碎念

知乎:wacky

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284379.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284379.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284379.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

shell printf命令:格式化輸出語句

shell printf命令:格式化輸出語句注意:使用printf的腳本比使用echo移植性好。如同echo命令,printf命令可以輸出簡單的字符串:[rootmaster ~]#printf "Hello, Shell\n"Hello, Shellprintf不像echo那樣會自動提供一個換行…

UVa 10905 孩子們的游戲

https://vjudge.net/problem/UVA-10905 題意&#xff1a; 給定n個正整數&#xff0c;把它們連接成一個最大的整數。 思路&#xff1a; 實在是沒想到直接用string來排序了。 1 #include<iostream> 2 #include<algorithm>3 #include<string>4 using namespace …

laravel 內部驗證碼

為什么80%的碼農都做不了架構師&#xff1f;>>> 1.找到此文件composer.json 如下圖添加 "gregwar/captcha": "1.*" 行代碼 2.在命令行中執行 composer update 安裝完成后 3.找到控制器添加如下代碼 public function captcha($tmp) {//生成驗證…

k8s docker集群搭建

一、Kubernetes系列之介紹篇 1.背景介紹 云計算飛速發展 - IaaS - PaaS - SaaS Docker技術突飛猛進 - 一次構建&#xff0c;到處運行 - 容器的快速輕量 - 完整的生態環境 2.什么是kubernetes 首先&#xff0c;他是一個全新的基于容器技術的分布式架構領先方案。Kubernetes(k8…

leetcode 66 Plus One

給定一個數組&#xff0c;表示整數的各個位數&#xff0c;現要將其加上1&#xff0c;考慮進位。 vector<int> plusOne(vector<int>& digits) {int size digits.size();bool carry true;for (int i size - 1; i > 0; --i) {if (digits[i] 9 && c…

如何讓最小 API 綁定查詢字符串中的數組

前言在上次的文章中&#xff0c;我們實現了《讓 ASP.NET Core 支持綁定查詢字符串中的數組》&#xff1a;[HttpGet] public string Get([FromQuery][ModelBinder(BinderType typeof(IntArrayModelBinder))] int[] values) {return string.Join(" ", values.Select(p…

Kubernetes api-server源碼閱讀2(Debug Kubernetes篇)

云原生學習路線導航頁&#xff08;持續更新中&#xff09; 本文是 Kubernetes api-server源碼閱讀 系列第二篇&#xff0c;主要講述如何實現 kubernetes api-server 的 debug 參考b站視頻地址&#xff1a;Kubernetes源碼開發之旅二 1.本篇章任務 Go-Delve&#xff1a;go語言的…

webrtc 視頻 demo

webrtc 視頻 demo webrtc網上封裝的很多&#xff0c;demo很多都是一個頁面里實現的&#xff0c;今天實現了個完整的 &#xff0c; A 發視頻給 BA webrtc.html作為offer <!DOCTYPE html> <html id"home" lang"en"><head><meta http-e…

條件注釋判斷瀏覽器版本!--[if lt IE 9](轉載)

<!--[if !IE]><!--> 除IE外都可識別 <!--<![endif]--> <!--[if IE]> 所有的IE可識別 <![endif]--> <!--[if IE 6]> 僅IE6可識別 <![endif]--> <!--[if lt IE 6]> IE6以及IE6以下版本可識別 <![endif]--> <!--[if …

[轉]阿里開源低代碼引擎LowCodeEngine

一、什么是低代碼引擎 低代碼引擎是具備強大擴展能力的低代碼研發框架&#xff0c;使用者只需要基于低代碼引擎便可以快速定制符合自己業務需求的低代碼平臺。同時&#xff0c;低代碼引擎還在標準低代碼設計器的基礎上提供了簡單易用的定制擴展能力&#xff0c;能夠滿足業務獨特…

Beyond Istio OSS——Istio服務網格的現狀與未來

作者&#xff1a;宋凈超&#xff08;Jimmy Song&#xff09;&#xff0c;原文地址&#xff1a;https://jimmysong.io/blog/beyond-istio-oss/本文根據筆者在 GIAC 深圳 2022 年大會上的的演講《Beyond Istio OSS —— Istio 的現狀及未來》[1] 整理而成&#xff0c;演講幻燈片見…

js多維數組扁平化

數組扁平化&#xff0c;就是將多維數組碾平為一維數組&#xff0c;方便使用。 一&#xff1a;例如&#xff0c;一個二維數組 var arr [a, [b, 2], [c, 3, x]]&#xff0c;將其扁平化&#xff1a; 1. 通過 apply 借用數組的 concat 方法&#xff1a; [].concat.apply([], arr)…

第16講 用戶程序的結構與執行

轉載于:https://www.cnblogs.com/atuo/p/5609843.html

兩種方法清除Excel保護密碼

一、利用VBA腳本直接清除 打Excel&#xff0c;打開腳本編輯器&#xff08;AltF11&#xff09;或者如圖&#xff0c;右鍵sheet名稱 輸入代碼并運行&#xff0c;即可清除密碼保護&#xff1a; Sub DeletePW()ActiveSheet.Protect DrawingObjects:True, Contents:True, AllowFil…

jsonp-反向代理-CORS解決JS跨域問題的個人總結

jsonp-反向代理-CORS解決JS跨域問題的個人總結 網上說了很多很多&#xff0c;但是看完之后還是很混亂&#xff0c;所以我自己重新總結一下。解決 js 跨域問題一共有8種方法&#xff0c; jsonp&#xff08;只支持 get&#xff09;反向代理CORSdocument.domain iframe 跨域windo…

URAL 1682 Crazy Professor (并查集)

【題目鏈接】 http://acm.timus.ru/problem.aspx?space1&num1682 【題目大意】 給出k&#xff0c;從1開始不斷地加一并把這個數寫在黑板上&#xff0c;如果寫上的數字和之前的數字滿足   (ab*b)%k0或者(ba*a)%k0就在他們之間連一條線&#xff0c;如果黑板上出現環就結束…

利用Python隨機或暴力生成密碼

""" Title: python 密碼生成 Author: JackieZheng Date: 2022-04-09 12:47:33 LastEditTime: 2022-04-09 14:00:46 LastEditors: Please set LastEditors Description: FilePath: \\pythonCode\\python_pwd_generater.py """import itertools im…

EasyNetQ-用于使用 RabbitMQ 的 .NET API開源的工具庫

Part1介紹EasyNetQ 的目標是提供一個庫&#xff0c;用于在 .NET 中使用 RabbitMQ 盡可能簡單。為了做到這一點&#xff0c;它通過強制執行一些簡單的約定來以靈活性換取簡單性。這些包括&#xff1a;消息應該由 .NET 類型表示。消息應按其 .NET 類型進行路由。這意味著消息是由…

python 中 __name__ 的使用

1. 如果模塊是被導入&#xff0c;__name__的值為模塊名字2. 如果模塊是被直接執行&#xff0c;__name__的值為’__main__’Py1.py #&#xff01;/usr/bin/env python def test():print __name__ ,__name__ if __name__ __main__:test() Py2.py #&#xff01;/usr/bin/env pyt…

第6章 循環

6.1 range 函數用來創建一個數字列表&#xff0c;它的范圍是從起始數字開始到結束數字之前 1 >>> for x in range(0,5): 2 print(Hello %s % x) 3 4 Hello 0 5 Hello 1 6 Hello 2 7 Hello 3 8 Hello 4 1 >>> print(list(range(10,20))) 2 [10, 11, 12, …