最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解讀數(shù)據(jù)庫的嵌套查詢的性能問題

 更新時間:2023年03月15日 09:15:01   作者:id老貓  
這篇文章主要介紹了解讀數(shù)據(jù)庫的嵌套查詢的性能問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

解讀數(shù)據(jù)庫的嵌套查詢的性能

explain 是非常重要的性能查詢的工具?。?!

1、嵌套查詢

首先大家都知道我們一般不提倡嵌套查詢或是join查詢

原因在哪呢?

下面是一個簡單地嵌套查詢

SELECT id ,name ,age

FROM teacher

WHERE status=0 and name IN (?

SELECT name FROM student WHERE age >18

)

我們一開始設想的是先執(zhí)行內(nèi)部查詢,然后再執(zhí)行外部查詢的。

這是我們美好的愿景。

這個時候我們就可以使用explain來看一下這條語句的執(zhí)行過程是怎樣的

+------+--------------+-------------+--------+---------------+--------------+---------+------+------+-------------+
| id ? | select_type ?| table ? ? ? | type ? | possible_keys | key ? ? ? ? ?| key_len | ref ?| rows | Extra ? ? ? |
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+-------------+
| ? ?1 | PRIMARY ? ? ?| teacher ? ? | ALL ? ?| NULL ? ? ? ? ?| NULL ? ? ? ? | NULL ? ?| NULL |65712| Using where |
| ? ?1 | PRIMARY ? ? ?| <subquery2> | eq_ref | distinct_key ?| distinct_key | 4 ? ? ? | func | ? ?1 | ? ? ? ? ? ? |
| ? ?2 | DEPENDENT SUBQUERY| student ? ? | ALL ? ?| NULL ? ? ? ? ?| NULL ? ? ? ? | NULL ? ?| NULL | ?418 | Using where |

這里可以看到student表的select_type是DEPENDENT SUBQUERY

DEPENDENT SUBQUERY是什么意思呢?

翻譯就是依靠外層查詢

簡而言之就是student內(nèi)層查詢要依靠外層查詢

如上面顯示,teacher表中關聯(lián)行數(shù)是65712

那就意味著內(nèi)層查詢要執(zhí)行6萬次之多,肯定會很慢的。

但也不是所有的嵌套的select_type都是DEPENDENT SUBQUERY

比如還有MATERIALIZED類型,他就是sql自己進行的優(yōu)化,他會在第一次進行子查詢的時候建立一個臨時表,保證后續(xù)查詢的速度。

2、join查詢

join連接也是類似的,聯(lián)表查詢時,會有一個驅(qū)動表來作為原始數(shù)據(jù)的循環(huán)表。

如果使用的是left join那么左表就是這個驅(qū)動表,反之亦然

我們要盡量用小表來當做驅(qū)動表。如果實在不能判斷哪個比較合適就用join讓mysql來幫你做選擇,他會自動選擇一個小表來做驅(qū)動表。

3、解決方法

1、首先,最直接簡單地方法就是不使用嵌套查詢。

使用多個單個的查詢來代替嵌套查詢

2、其次,我們還可以使用臨時表進行簡單地嵌套查詢

SELECT id ,name ,age

FROM teacher t, (SELECT name FROM student WHERE age>18) s

WHERE t.status=0 and t.name=s.name

)

問題:數(shù)據(jù)庫內(nèi)部嵌套關系實現(xiàn)

我在做報表的時候遇到一個問題,想了很長時間沒有解決,后來轉(zhuǎn)換思路一下子就解決了。具體問題是這樣的,我們公司有一張行業(yè)表,總共有四級行業(yè)需要維護,具體包括一級行業(yè)、二級行業(yè)、三級行業(yè)和四級行業(yè),每個行業(yè)之間又存在包含關系,比如四級行業(yè)包含于三級行業(yè),三級行業(yè)包含于二級行業(yè),二級行業(yè)包含于一級行業(yè),最詭異的地方就是我們把這么多信息放在一張表里維護,只不過額外加了兩個字段以示區(qū)分,一個是行業(yè)等級,一個是父行業(yè),具體的表結構如下:

行業(yè)ID行業(yè)等級父行業(yè)ID
二級行業(yè)二級一級行業(yè)
三級行業(yè)1三級二級行業(yè)
三級行業(yè)2三級二級行業(yè)
四級行業(yè)1四級三級行業(yè)1
四級行業(yè)2四級三級行業(yè)2

最后的需求是有另外一張表,是用四級行業(yè)劃分的,其中有一項費用,最后需要按一級行業(yè)統(tǒng)計每個行業(yè)的費用。

模型

根據(jù)實際業(yè)務,為了說明這個問題,筆者在這里做了一個模型簡化,假設我們只有兩張表tb_cls和tb_cost,tb_cls包含行業(yè)id,行業(yè)等級cls,父行業(yè)p_id,所有行業(yè)(包括一級、二級、三級行業(yè)都保存在這張表里)都包含在內(nèi),具體創(chuàng)建出來的表如下(為了讀者閱讀方便,這里做了一個簡化:id前面的第一位數(shù)代表一級行業(yè)編碼,例如121表示屬于一級大行業(yè);整個id的位數(shù)代表幾級行業(yè),例如211總共三位表示三級行業(yè)):

另外一張表,我也做了簡化,只提取其中用到的行業(yè)id和費用兩個字段,具體的表內(nèi)容如下:

問題

我們現(xiàn)在的任務有兩個:

  • 第一、建立三級行業(yè)跟一級行業(yè)一一對應關系;
  • 第二、按一級行業(yè)統(tǒng)計費用。

思路

彎路:

最開始的思路是嵌套,就是根據(jù)現(xiàn)實世界的邏輯關系一層一層建立聯(lián)系,SELECT * FROM tb WHERE id IN(SELECT * FROM tb WHERE),沿著這個思路嘗試了很多,首先在SELECT外層聲明的變量內(nèi)層的嵌套識別不了,內(nèi)外層建立的變量不能相互訪問,另外一個這種建立起來的關系,沒有一一對應關系,因為我們用的是IN,最終只要存在就可以,所以沒有嚴格的一一對應關系。具體思路如下:

1.1 第1層:

SELECT id FROM tb_cost

1.2 第2層:

SELECT p_id FROM tb_cls WHERE id IN(SELECT id FROM tb_cost) AND cls=3

1.3 第3層:

SELECT p_id FROM tb_cls WHERE id IN(SELECT p_id FROM tb_cls WHERE id IN(SELECT id FROM tb_cost) AND cls=3) AND cls=2

1.4 第4層(最終):

SELECT t1.id,t2.id FROM tb_cls AS t1,tb_cost AS t2 WHERE t1.id IN(SELECT p_id FROM tb_cls WHERE id IN(SELECT p_id FROM tb_cls WHERE id IN(SELECT id FROM tb_cost) AND cls=3) AND cls=2)AND cls=1;

最終查詢的結果如下:

發(fā)現(xiàn)那里不對了沒有,每個一級行業(yè)下面包含所有的三級行業(yè),所以這種嵌套方式走不通,同時進一步深入下去研究發(fā)現(xiàn)嵌套內(nèi)外層定義的變量是不能相互交互的,什么意思呢?

SELECT t1.id, var_1 FROM t1 WHERE p_id IN(SELECT id AS var_1 FROM t1)var_1變量在內(nèi)層那個SELECT是不可用的。

新思路:

基于上面的彎路,筆者換了一個,假設我們有3張一模一樣的表,通過這3張不同的表來區(qū)分各自的邏輯關系,把這3張表看成不同的表,一個個添加條件,具體思路如下:

2.1 第1層:tb_cls(AS t3)三級行業(yè)跟tb_cost(AS t4)建立關聯(lián):t3.id=t4.id AND t3.cls=3

2.2 第2層:tb_cls(AS t2)二級行業(yè)跟tb_cls(AS t3)建立關聯(lián):t3.p_id=t2.id AND t2.cls=2

2.3 第3層:tb_cls(AS t1)一級行業(yè)跟tb_cls(AS t2)建立關聯(lián):t2.p_id=t1.id AND t1.cls=1

最終,建立起來的三級行業(yè)對應一級行業(yè)的對應關系如下:

SELECT t1.id,t4.id FROM tb_cls AS t1,tb_cls AS t2,tb_cls AS t3,tb_cost AS t4 WHERE t4.id=t3.id AND t3.p_id=t2.id AND t2.p_id=t1.id AND t3.cls=3 AND t2.cls=2 AND t1.cls=1;

查詢結果如下,跟我們實際建立的情況一致,第一個任務(第一、建立三級行業(yè)跟一級行業(yè)一一對應關系)完成。 

解決了第一個任務,第二個任務就簡單多了,其實就是按照一級行業(yè)id加個GROUP BY,分一下組就可以,

具體語句如下:

SELECT t1.id,SUM(t4.cost) FROM tb_cls AS t1,tb_cls AS t2,tb_cls AS t3,tb_cost AS t4 WHERE t4.id=t3.id AND t3.p_id=t2.id AND t2.p_id=t1.id AND t3.cls=3 AND t2.cls=2 AND t1.cls=1 GROUP BY t1.id;

查詢結果如下,簡單計算一下一級、二級、三級費用是不是查詢出來的值,至此,任務二也圓滿完成。

總之,當我們需要解決SQL語句的查詢?nèi)蝿盏臅r候,不要一味的選擇深奧的技術、邏輯復雜的語言去解決(像筆者這里用多層嵌套,最后把自己繞進去了。)首先我們要做的是簡化邏輯,能通過簡單的思路解決復雜的問題本身也是一種能力,在這個基礎上然后基于性能、需求、業(yè)務慢慢再繼續(xù)優(yōu)化SQL才是我們應該做的。

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 完美解決mysql客戶端授權后連接失敗的問題

    完美解決mysql客戶端授權后連接失敗的問題

    下面小編就為大家?guī)硪黄昝澜鉀Qmysql客戶端授權后連接失敗的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • MySQL的隱式類型轉(zhuǎn)換整理總結

    MySQL的隱式類型轉(zhuǎn)換整理總結

    隱式類型轉(zhuǎn)換有無法命中索引的風險,在高并發(fā)、大數(shù)據(jù)量的情況下,命不中索引帶來的后果非常嚴重。下面這篇文章主要給大家整理總結了關于MySQL的隱式轉(zhuǎn)化,需要的朋友可以參考借鑒,下面來一起看看吧。
    2016-12-12
  • Mysql數(shù)據(jù)庫的日志管理、備份與回復詳細圖文教程

    Mysql數(shù)據(jù)庫的日志管理、備份與回復詳細圖文教程

    備份的主要目的是災難恢復,備份還可以測試應用、回滾數(shù)據(jù)修改、查詢歷史數(shù)據(jù)、審計等,這篇文章主要給大家介紹了關于Mysql數(shù)據(jù)庫的日志管理、備份與回復的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-08-08
  • MySQL?EXPLAIN執(zhí)行計劃解析

    MySQL?EXPLAIN執(zhí)行計劃解析

    本文主要介紹了MySQL?EXPLAIN執(zhí)行計劃解析,通過MySQL?EXPLAIN執(zhí)行計劃的各個字段的含義以及使用方式。感興趣的小伙伴可以參考一下
    2022-08-08
  • MySQL group by分組后如何將每組所得到的id拼接起來

    MySQL group by分組后如何將每組所得到的id拼接起來

    這篇文章主要介紹了MySQL group by分組后如何將每組所得到的id拼接起來,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Mysql經(jīng)典高逼格/命令行操作(速成)(推薦)

    Mysql經(jīng)典高逼格/命令行操作(速成)(推薦)

    這篇文章主要介紹了Mysql命令行操作,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • 如何安裝MySQL Community Server 5.6.39

    如何安裝MySQL Community Server 5.6.39

    這篇文章主要為大家詳細介紹了MySQL Community Server 5.6.39安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • MySQL中B樹索引和B+樹索引的區(qū)別詳解

    MySQL中B樹索引和B+樹索引的區(qū)別詳解

    這篇文章主要為大家詳細介紹了MySQL中B樹索引和B+樹索引的區(qū)別,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • MySQL命令行導出導入數(shù)據(jù)庫實例詳解

    MySQL命令行導出導入數(shù)據(jù)庫實例詳解

    這篇文章主要介紹了MySQL命令行導出導入數(shù)據(jù)庫實例詳解的相關資料,需要的朋友可以參考下
    2016-10-10
  • MySQL ifnull()函數(shù)的具體使用

    MySQL ifnull()函數(shù)的具體使用

    本文主要介紹了MySQL ifnull()函數(shù)的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08

最新評論

霞浦县| 隆尧县| 巴南区| 万源市| 库车县| 长岛县| 潞西市| 新建县| 霸州市| 玉屏| 乌拉特前旗| 高州市| 鄂托克旗| 二连浩特市| 呼伦贝尔市| 辛集市| 庆阳市| 隆化县| 镇远县| 大新县| 临沂市| 杭锦旗| 泊头市| 大冶市| 泸水县| 珠海市| 武安市| 新丰县| 许昌市| 铜山县| 太湖县| 襄汾县| 华容县| 宜丰县| 卢氏县| 绥芬河市| 聂拉木县| 泌阳县| 博罗县| 丘北县| 宿迁市|