SQL 語言最佳實踐
爲單位制訂的 SQL 規範,分享一下。
首先說一下,這是公司用的一個規範,給到程序員做參考的。
其實,這個規範是建立在對 SQL 有一定熟悉程序的基礎上的,所以規範本身並不涉及 SQL 語法學習的相關內容。
- 絕對避免使用 SELECT *
SELECT * 查詢會返回所有列的記錄。這樣的查詢會有很多問題:
-
很多情況不需要檢索所有的字段,使用 SELECT * 會消耗過多的帶寬;
-
在考慮到修改表結構的前題並存在髒數據的情況,SELECT * 出現意想不到的結果;
-
SELECT * 比 SELECT [字段] 要慢,因爲後者可以使用列索引;
-
SELECT * 返回的列順序不可控。
因此,要求查詢時逐個列表需要查詢的字段。包括查詢全部字段,也需要將字段逐個寫出來,並按照需要的方式排序字段的先後次序。
- 區分使用 WHERE 和 HAVING
SQL 中 WHERE 和 HAVING 從語法上可以在一定範圍內混着用,但兩個詞的語義截然不同,在實際編程時,需要按語義分開使用。
-
WHERE 用於全部 CRUD,HAVING 只用於查詢 SELECT;
-
WHERE 用在聚合操作之前過濾數據,HAVING 用在聚合之後;
-
HAVING 子句中可以使用聚合函數,如 SUM、MIN、MAX、COUNT,而 WHERE 子句不能使用聚合函數,除非該子句是 HAVING 子句中包含的子查詢的一部分。
- 表連接查詢使用 INNER JOIN
JOIN 是使用非常多的 SQL 查詢之一,允許用戶從多個表中選擇數據。WHERE 也可以連接兩個表並獲取聚合數據,但開發中禁止使用。
一個主要的原因是 WHERE 返回的是 CROSS JOIN,返回的記錄數是兩個表記錄的乘積。例如兩個表 A 和 B,各有 1000 條數據,用 WHERE 子句,將會返回一個 1000 x 1000 = 1000000 條記錄的 CROSS JOIN,然後再從這個數據集裏提取滿足條件的數據。這在性能上不可接受。
而上面的例子,在 INNER JOIN 時僅返回 1000 條記錄,然後從這個數據集中提取滿足條件的數據。
雖然有些數據庫會在內部將 JOIN 查詢中的 WHERE 轉換爲 INNER JOIN,但規則要求顯式使用 INNER JOIN,而不是 WHERE。
- 使用 EXISTS 和 NOT EXISTS 代替 IN 和 NOT IN
在檢索某個值在表中存在與否時,EXISTS 子句的執行進程會在找到值後停卡,而 IN 子句會在找到值後繼續掃描所有的值。
NOT EXISTS 和 NOT IN 的執行也一樣。
這個規則也是性能原因。
- 使用 = 代替 LIKE
兩個方式都可以用來匹配字符串,但 LIKE 用於匹配通配符,而 = 用來進行精確匹配。
在 SQL 中,= 操作符可以使用索引,會比 LIKE 更快。
- 使用 LIMIT 子句限制檢索結果數量
查詢數據時,儘可能使用 LIMIT 子句,來限制查詢結果數量。大多數情況下,查詢沒有必要返回所有行。限制查詢返回的數量,也可以提高查詢性能。
- 查詢多表時使用表別名
多表查詢時,使用表別名,避免混淆,並防止數據庫在搜索列表所屬的表時解析列名。這不會增加工作量,但很有效。
- 避免使用 “sp_” 作爲存儲過程的名稱前綴
原則上,避免使用存儲過程。
如果必須使用存儲過程,那必須禁止使用 sp_
作爲前綴的存儲過程名稱。SQL Server 中,會首先在主數據庫中查詢名稱以 sp_
開頭的存儲過程,然後再搜索其它地方。因此,避免 sp_
打頭的存儲過程名稱可以節省大量時間,SQL Server 將直接檢查 DBO 作爲存儲過程的所有者,而不是在主數據庫中查找存儲過程。
- 採用規範的查詢代碼風格
這算是一個建議,但是,使用良好規範的代碼風格是必要的:
-
完整的註釋。需要幫助其它團隊成員理解查詢的目的,並提醒開發者做的是什麼;
-
使用明顯的命名約定。數據庫、表名、字段名,包括臨時表和變量名都應該是可讀和清楚的;
-
儘可能縮進查詢語句。通過縮進來確保清晰的代碼外觀,並提高查詢的可讀性。
SQL 是一種非常靈活的語言,提供了多種方法在數據庫上執行所需的任務。在編程中,性能瓶頸大多來自數據庫操作和響應。以上這些建議,可能有效地幫助加快性能,消除不必要的延時,並可避免長期積累的數據庫問題。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/h_CvkEJVlQUFCbhvLSMKQw