讓SQL再快一點兒

SQL 編程語言 文章 開發者圓桌 2017-05-28

本文轉自「開發者圓桌」一個10年老猿原創文章傳播開發經驗,尤其適合初學者或剛入職場前幾年程序猿的微信公眾號。

SQL即結構化查詢語言(Structured Query Language),是一種特殊目的的編程語言,是一種數據庫查詢和程序設計語言,用於存取數據以及查詢、更新和管理關係型數據庫系統。

從接觸編程到現在一直從事和數據庫相關的工作,SQL是我使用時間最長的程序語言,沒有之一。

關於SQL優化的文章網上很多,很具體,寫的很不錯,這裡不再贅述。這篇文章將會結合平時工作中遇到的問題和經驗心得來闡述如何做好SQL優化,其中有錯誤和不足的地方,還請大家糾正補充。

對於數據庫優化有兩個層面,一是SQL優化,屬於業務層優化;一是數據庫設計、表空間規劃、緩存等屬於管理層面的優化,我們這裡只討論SQL優化這個層面。

接受挑戰

不要被運行效率低下或者複雜的SQL嚇倒,要勇於接收它的挑戰,問題很明確就是要把這個SQL優化快一點,解決方法肯定比遇到的問題多。

越是運行慢,越是複雜的SQL優化的空間就越大。

分析場景

數據處理大致可以分成兩大類:聯機事務處理OLTP(on-line transaction processing)、聯機分析處理OLAP(On-Line Analytical Processing)。OLTP是傳統的關係型數據庫的主要應用,主要是基本的、日常的事務處理,例如銀行交易。OLAP是數據倉庫系統的主要應用,支持複雜的分析操作,側重決策支持,並且提供直觀易懂的查詢結果。

OLTP 系統強調數據庫內存效率,強調內存各種指標的命令率,強調綁定變量,強調併發操作,對於SQL的執行效率有很高的要求;

OLAP 系統則強調數據分析,強調SQL執行時機,強調磁盤I/O,強調分區等。

OLTP要求事務一致性和快速執行,SQL執行時間一般以毫秒或者秒為單位;OLAP對事務一致性要求不高,SQL執行時間以分鐘或者小時為單位。因此,不同的業務場景,SQL優化的方法也是不同的。

定位SQL優化點

由於數據庫產品、參數配置甚至同一款產品的不同發行版本都會導致同一條SQL出現不同的運行效率。隨著業務數據的增長,原本運行良好的SQL也會出現瓶頸。

變化再多也有規律可循,SQL運行效率低根本的問題就是SQL表關聯太多、SQL邏輯太複雜、表數據量太大、未使用索引等,這些就是我們要優化的點。

拿到運行效率低的SQL以後,要分析一下該條SQL用到哪些表?哪些索引?表中的數據量是多少?對整個SQL運行的基礎環境有一個清晰的認識。

優化SQL最常用的輔助工具就是數據庫本身提供的“執行計劃”,如何開啟、使用執行計劃分析和優化SQL,可點擊文章最後左下角「閱讀原文」查看之前整理的一篇關於《數據庫SQL執行計劃應用初探》的文章。

進行SQL優化

定位到SQL執行效率低下的原因以後,要想辦法優化它,下面是一些通用的處理思路,可以參考一二。

索引;索引是關係型數據庫中SQL優化的利器,設計良好的索引以及在SQL中正確應用索引基本上能解決大部分的SQL優化問題。可以通過執行計劃分析SQL中索引的應用情況。

變通;3+6與4+5的結果都是9,做事的方式並不是唯一的,可能一種SQL寫法效率很低,然而你換一個思路試試其他的寫法,效率會有很大的提升,這個需要不斷的嘗試和摸索。

舉個栗子,以Oracle為例查詢公司男性與女性員工的薪資總和

select

(select sum(salary) from employee where sex='男') 男性薪資總和,

(select sum(salary) from employee where sex='女') 女性薪資總和

from dual

更好的寫法應該是

select

sum(case when sex='男' then salary else 0 end) 男性薪資總和,

sum(case when sex='女' then salary else 0 end) 女性薪資總和

from employee

我剛入門SQL時,就是採用了第一種寫法,邏輯最簡單明瞭,但是一個employee表卻被掃描了兩次(在沒有索引的情況下),隨著數據量的增加,這條SQL必然出現效率低的問題,第二種寫法就會優化很多,效率更高。這是一個簡單不能再簡單的變通了(當然是現在看來,當時可能想不到)。

分解;把複雜的一條SQL可以拆解為多條簡單SQL分步驟執行,可能你會覺得分步驟執行做了很多額外的工作,但是每條簡單的SQL執行的會非常快,整體上提升了SQL執行效率。

SQL分解最常用的就是創建中間表,中間表只保存需要的字段和數據行,同時增加必要的索引,可大大提升SQL的執行效率。

環境;SQL優化要在同一個環境中進行,不同的環境中SQL執行路徑可能是不同的,優化的方法也是不同的。儘量排除環境因素對SQL優化的影響。

經驗;經驗很重要,但是避免陷入經驗主義。你可能在Oracle中有著非常豐富的SQL優化經驗,但是在DB2數據庫中可能就不靈了,不要糾結,這很正常。在我從Oracle數據庫轉向DB2數據庫時就出現了很多問題,在Oracle中積累的經驗轉移到DB2中行不通,只能另闢蹊徑。

SQL優化需要經驗,但是不能太依賴經驗,要不斷調整自己的思路。每款數據庫產品都有自己的特點,要了解它們,然後去不斷應用。好在大部分的經驗是通用的,只是略加調整即可,不要太大壓力。

把平時優化SQL的技巧和方法總結下來,在真實的SQL優化場景中反覆使用和調整,逐漸形成自己的一套優化經驗。

總結

上面總結了一些我個人的SQL優化經驗,包治百病的良藥是不存在的,具體問題還是需要當事人具體分析,優化思路是相通的。

SQL優化這事兒不需要刻意為之,當你寫的SQL不滿足業務要求時自然就要優化,每次的SQL優化都會不斷提升你的優化能力和思考方式。

相關推薦

推薦中...