怎樣評價一個幾千行的 SQL 儲存過程

dbLenis發表於2019-02-16

前兩天在知乎逛街,看到有這麼個話題,順手回答了下,並分享在這裡,喜歡的話就一起討論討論吧。

幾千行的 SQL 儲存過程,在比較老式的開發架構中常見,起源於 C/S 年代。通常是前端沒有引入適當框架的設計,而將所有的應用邏輯一股腦兒丟給資料庫開發造成的。當然這類設計的好處是上線快速,極短時間便可拿下專案。而弊端是擴充套件起來麻煩,尤其資料庫開發一旦跳槽之後,留下的往往是看不懂的上古祖傳程式碼,此時再動刀擴充套件系統架構去支撐業務需求,就顯得吃力。

作為負責的資料庫開發,拿到這大幾千行的 SQL 程式碼,肯定是不能聽之任之的。

首先,理解程式碼

越長的 SQL 越是要理解透徹。開發為了省事(專案負責人好好檢討)憑著腦袋想到哪裡,寫到哪裡,沒有通盤考慮邏輯的合理性與程式的可讀性。有時候明明可以用一句 update 完成的操作,有些開發笨拙的拆開了很多次去操作,原因很可能是為了去記 log, 或者多個條件不懂得去歸併。前者是設計的錯誤,後者是 SQL 本質思想的理解不到位。

在動手改程式碼之前,一定要理解透徹程式碼,不能操之過急。往往像這類耦合度高的 SQL 應用邏輯,好幾個地方都在用,改了之後不一定會給哪裡造成 bug.

接著,分拆程式碼

在理解透徹業務邏輯的基礎上,對程式碼進行整塊的分拆和聚合。分拆和聚合的關鍵是控制事務。主表一級的事務,子表一級的事務,是不是可以分開處理,還是必須聯合處理。是否考慮用多個子儲存過程來格式化程式碼,顯得更加易讀,邏輯上也更加易懂。

分拆程式碼的好處是可以讓你快速掌握業務邏輯,熟絡每個業務關鍵點,重點是培養對業務的敏感。

再接著,改寫程式碼

當已經把程式碼段落按照業務邏輯分拆,合併之後,接下來就是在 SQL 細節層面做優化。這時候首先要考慮 SQL 語言的特點,集合化思想。如果你有魔方,可以拿起來看下,SQL 處理的是面以及面與面之間的關係。

怎樣評價一個幾千行的 SQL 儲存過程

如果要把紅色的方塊都選中,有的開發朋友會將第 1, 2,3 行的篩選條件單獨拿出來,各自選出來之後再塞到臨時表去做聚合,而正確的做法是將 1, 2, 3 的篩選條件首先聚合,歸併,使用一條 SELECT 或 Update 語句完成原本冗餘的程式碼。

在命名規範,Magic Number,低效率 SQL 編碼上都要做嚴格審查,防止程式碼的腐化。不好的 SQL 程式碼習慣看到很多,直接寫 insert ... select * from /update/delete 都是要嚴格禁止的;在大併發的系統中,使用臨時表裝載大量資料來滿足報表需求,也是要適可而止的;OLTP 要和 OLAP 嚴格分開庫,這種並存一庫的架構至今在很多單位還存在著。

最後,儲存程式碼

任何程式碼都需要進 Source Code Version Control. 無論是 Git/SVC/TFS, 針對遺留程式碼,新增程式碼都要進行完整的原始碼版本控制,做到有源可溯。

為什麼會有這大幾千行的 SQL 程式碼呢,我猜原因有 2 :

1 專案趕,時間緊,一切 以上線為重。自以為上線後會修改自己的程式碼,往往不大可能。就算你有心,後面的專案需求也會把你的積極性消磨殆盡。一旦專案結束,你跳槽,薪水翻倍了,再回頭就沒有機會了。

2 寫 SQL 不寫草稿。這個習慣可能大部分人都會覺得很奇怪,寫程式碼還寫草稿?其實程式碼和寫作一樣,都是一種表達。村上春樹寫小說都打草稿,還修改不止一兩遍。博爾赫斯等大文豪,對於修改是非常執著的。沒有四五遍修改,都不好意思見人。我們有些程式設計師就是太貪,太急,潦草完事,從不往回找找感覺。看到業務就想接,這樣不是不好,但總結歸納本就是一門提高效率的學問,舉一反三手藝才能穩步提高。

有多少朋友,Pivot 總是寫得不順手,歸根結底就是對寫過的程式碼不總結,而寫草稿,恰恰給你一個總結的過程。

相關文章