首頁 系統教程 Linux 終極指南-如何寫出更好的SQL查詢?

終極指南-如何寫出更好的SQL查詢?

Jan 12, 2024 pm 12:15 PM
linux linux教程 紅帽 linux系統 linux指令 linux認證 紅帽linux linux視頻

基於集合和程式的方法進行查詢

反向模型中隱含的事實是,建立查詢時基於集合和程序的方法之間存在著不同。

  • 查詢的程式方法是一種非常類似於程式設計的方法:你告訴系統需要做些什麼以及如何做。例如上一篇文章中的範例,透過執行函數然後呼叫另一個函數來查詢資料庫,或使用包含循環、條件和使用者定義函數(UDF)的邏輯方式來獲得最終查詢結果。你會發現透過這種方式,一直在要求一層一層中資料的子集。這種方法也常被稱為逐步或逐行查詢。
  • 另一種是基於集合的方法,只需指定需要執行的操作。使用這種方法要做的事情就是,指定你想透過查詢獲得的結果的條件和要求。在檢索資料過程中,你不需要專注於實作查詢的內部機制:資料庫引擎會決定最佳的執行查詢的演算法和邏輯。

由於 SQL 是基於集合的,所以這種方法比起程式方法更有效,這也解釋了為什麼在某些情況下,SQL 可以比程式碼工作地更快。

基於集合的查詢方法也是資料探勘分析產業要求你必須掌握的技能!因為你需要熟練的在這兩種方法之間進行切換。如果你發現自己的查詢中存在程式查詢,則應該考慮是否需要重寫這部分。

終極指南-如何寫出更好的SQL查詢?

#從查詢到執行計劃

反向模式不是靜止不變的。在你成為 SQL 開發者的過程中,避免查詢反向模型和重寫查詢可能會是一個很艱難的任務。所以時常需要使用工具以更結構化的方法來優化你的查詢。

對效能的思考不僅需要更結構化的方法,還需要更深入的方法。

然而,這種結構化和深入的方法主要是基於查詢計劃的。查詢計劃首先被解析為“解析樹”並且準確地定義了每個操作使用什麼演算法以及如何協調操作過程。

查詢最佳化

在最佳化查詢時,很可能需要手動檢查優化器產生的計劃。在這種情況下,將需要透過查看查詢計劃來再次分析你的查詢。

要掌握這樣的查詢計劃,你需要使用一些資料庫管理系統提供給你的工具。你可以使用以下的一些工具:

  • 一些軟體包功能工具可以產生查詢計劃的圖形表示。
  • 其它工具能夠為你提供查詢計劃的文字描述。

請注意,如果你正在使用 PostgreSQL,則可以區分不同的 EXPLAIN,你只需取得描述,說明 planner 如何在不執行計劃的情況下執行查詢。同時 EXPLAIN ANALYZE 會執行查詢,並傳回給你一個評估查詢計畫與實際查詢計畫的分析報告。一般來說,實際執行計劃會實際的執行這個計劃,而評估執行計劃可以在不執行查詢的情況下,解決這個問題。在邏輯上,實際執行計劃更為有用,因為它包含了執行查詢時,實際發生的其它細節和統計資料。

接下來你將了解 XPLAIN 和 ANALYZE 的更多信息,以及如何使用這兩個命令來進一步了解你的查詢計劃和查詢性能。要做到這一點,你需要開始使用兩個表: one_million 和 half_million 來做一些範例。

你可以藉助 EXPLAIN 來擷取 one_million 表的目前資訊:確保已將其放在執行查詢的首要位置,在執行完成之後,會回到查詢計畫中:

EXPLAIN
SELECT *
FROM one_million;
QUERY PLAN
<span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-emphasis">___</span>_
Seq Scan on one_million
(cost=0.00..18584.82 rows=1025082 width=36)
(1 row)
登入後複製

在上述範例中,我們看到查詢的 Cost 是0.00..18584.82 ,行數是1025082,列寬是36。

同時,也可以藉助 ANALYZE 來更新統計資料  。

ANALYZE one_million;
EXPLAIN
SELECT *
FROM one_million;
QUERY PLAN
<span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-emphasis">___</span>_
Seq Scan on one_million
(cost=0.00..18334.00 rows=1000000 width=37)
(1 row)
登入後複製

除了 EXPLAIN 和 ANALYZE,你也可以藉助 EXPLAIN ANALYZE 來擷取實際執行時間:

EXPLAIN ANALYZE
SELECT *
FROM one_million;
QUERY PLAN
<span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span>_
Seq Scan on one_million
(cost=0.00..18334.00 rows=1000000 width=37)
(actual time=0.015..1207.019 rows=1000000 loops=1)
Total runtime: 2320.146 ms
(2 rows)
登入後複製

使用 EXPLAIN ANALYZE 的缺點就是需要實際執行查詢,這一點值得注意!

到目前為止,我們看到的所有演算法都是順序掃描或全表掃描:這是一種在資料庫上進行掃描的方法,掃描的表的每一行都是以順序(串行)的順序進行讀取,每一列都會檢查是否符合條件。在效能方面,順序掃描不是最佳的執行計劃,因為需要掃描整個表格。但是如果使用慢磁碟,順序讀取也會很快。

還有一些其它演算法的範例:

EXPLAIN ANALYZE
SELECT *
FROM one<span class="hljs-emphasis">_million JOIN half_</span>million
ON (one<span class="hljs-emphasis">_million.counter=half_</span>million.counter);
QUERY PLAN
<span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span><span class="hljs-strong">_____</span>_
Hash Join (cost=15417.00..68831.00 rows=500000 width=42)
(actual time=1241.471..5912.553 rows=500000 loops=1)
Hash Cond: (one<span class="hljs-emphasis">_million.counter = half_</span>million.counter)
<span class="hljs-code">    -> Seq Scan on one_million</span>
<span class="hljs-code">    (cost=0.00..18334.00 rows=1000000 width=37)</span>
<span class="hljs-code">    (actual time=0.007..1254.027 rows=1000000 loops=1)</span>
<span class="hljs-code">    -> Hash (cost=7213.00..7213.00 rows=500000 width=5)</span>
<span class="hljs-code">    (actual time=1241.251..1241.251 rows=500000 loops=1)</span>
<span class="hljs-code">    Buckets: 4096 Batches: 16 Memory Usage: 770kB</span>
<span class="hljs-code">    -> Seq Scan on half_million</span>
<span class="hljs-code">    (cost=0.00..7213.00 rows=500000 width=5)</span>
(actual time=0.008..601.128 rows=500000 loops=1)
Total runtime: 6468.337 ms
登入後複製

我們可以看到查詢優化器選擇了 Hash Join。請記住這個操作,因為我們需要使用這個來評估查詢的時間複雜度。我們注意到了上面範例中沒有 half_million.counter 索引,我們可以在下面範例中新增索引  :

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> <span class="hljs-keyword">ON</span> half_million(counter);
<span class="hljs-keyword">EXPLAIN</span> <span class="hljs-keyword">ANALYZE</span>
<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> one_million <span class="hljs-keyword">JOIN</span> half_million
<span class="hljs-keyword">ON</span> (one_million.counter=half_million.counter);
QUERY PLAN
______________________________________________________________
<span class="hljs-keyword">Merge</span> <span class="hljs-keyword">Join</span> (<span class="hljs-keyword">cost</span>=<span class="hljs-number">4.12</span>.<span class="hljs-number">.37650</span><span class="hljs-number">.65</span> <span class="hljs-keyword">rows</span>=<span class="hljs-number">500000</span> width=<span class="hljs-number">42</span>)
(actual <span class="hljs-keyword">time</span>=<span class="hljs-number">0.033</span>.<span class="hljs-number">.3272</span><span class="hljs-number">.940</span> <span class="hljs-keyword">rows</span>=<span class="hljs-number">500000</span> loops=<span class="hljs-number">1</span>)
<span class="hljs-keyword">Merge</span> Cond: (one_million.counter = half_million.counter)
    -> <span class="hljs-keyword">Index</span> <span class="hljs-keyword">Scan</span> <span class="hljs-keyword">using</span> one_million_counter_idx <span class="hljs-keyword">on</span> one_million
    (<span class="hljs-keyword">cost</span>=<span class="hljs-number">0.00</span>.<span class="hljs-number">.32129</span><span class="hljs-number">.34</span> <span class="hljs-keyword">rows</span>=<span class="hljs-number">1000000</span> width=<span class="hljs-number">37</span>)
    (actual <span class="hljs-keyword">time</span>=<span class="hljs-number">0.011</span>.<span class="hljs-number">.694</span><span class="hljs-number">.466</span> <span class="hljs-keyword">rows</span>=<span class="hljs-number">500001</span> loops=<span class="hljs-number">1</span>)
    -> <span class="hljs-keyword">Index</span> <span class="hljs-keyword">Scan</span> <span class="hljs-keyword">using</span> half_million_counter_idx <span class="hljs-keyword">on</span> half_million
    (<span class="hljs-keyword">cost</span>=<span class="hljs-number">0.00</span>.<span class="hljs-number">.14120</span><span class="hljs-number">.29</span> <span class="hljs-keyword">rows</span>=<span class="hljs-number">500000</span> width=<span class="hljs-number">5</span>)
(actual <span class="hljs-keyword">time</span>=<span class="hljs-number">0.010</span>.<span class="hljs-number">.683</span><span class="hljs-number">.674</span> <span class="hljs-keyword">rows</span>=<span class="hljs-number">500000</span> loops=<span class="hljs-number">1</span>)
Total runtime: <span class="hljs-number">3833.310</span> ms
(<span class="hljs-number">5</span> <span class="hljs-keyword">rows</span>)
登入後複製

透過建立索引,查詢最佳化器已經決定了索引掃描時,如何找到 Merge join。

請注意,索引掃描和全表掃描(順序掃描)之間的區別:後者(也稱為「表掃描」)是透過掃描所有資料或索引所有頁面來查找到適合的結果,而前者只掃描表中的每一行。

教學的第二部分內容,就介紹到這裡。後續還會有《如何寫出更好的SQL查詢》系列的最後一篇文章,敬請期待。

轉載請註明出自:葡萄城控制

以上是終極指南-如何寫出更好的SQL查詢?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Android TV Box 獲得非官方 Ubuntu 24.04 升級 Android TV Box 獲得非官方 Ubuntu 24.04 升級 Sep 05, 2024 am 06:33 AM

Android TV Box 獲得非官方 Ubuntu 24.04 升級

deepseek網頁版入口 deepseek官網入口 deepseek網頁版入口 deepseek官網入口 Feb 19, 2025 pm 04:54 PM

deepseek網頁版入口 deepseek官網入口

deepseek怎麼安裝 deepseek怎麼安裝 Feb 19, 2025 pm 05:48 PM

deepseek怎麼安裝

BitPie比特派錢包app下載位址 BitPie比特派錢包app下載位址 Sep 10, 2024 pm 12:10 PM

BitPie比特派錢包app下載位址

BITGet官方網站安裝(2025新手指南) BITGet官方網站安裝(2025新手指南) Feb 21, 2025 pm 08:42 PM

BITGet官方網站安裝(2025新手指南)

詳解:Shell腳本變數判斷參數指令 詳解:Shell腳本變數判斷參數指令 Sep 02, 2024 pm 03:25 PM

詳解:Shell腳本變數判斷參數指令

Zabbix 3.4 原始碼編譯安裝 Zabbix 3.4 原始碼編譯安裝 Sep 04, 2024 am 07:32 AM

Zabbix 3.4 原始碼編譯安裝

歐易okx安裝包直接進 歐易okx安裝包直接進 Feb 21, 2025 pm 08:00 PM

歐易okx安裝包直接進

See all articles