共計 5151 個字符,預計需要花費 13 分鐘才能閱讀完成。
這篇文章主要講解了“MySQL 中寫 SQL 的好習慣有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學習“MySQL 中寫 SQL 的好習慣有哪些”吧!
1. 寫完 SQL 先 explain 查看執行計劃(SQL 性能優化)
日常開發寫 SQL 的時候,盡量養成這個好習慣呀:寫完 SQL 后,用 explain 分析一下,尤其注意走不走索引。
explain select userid,name,age from user where userid =10086 or age =18;
2、操作 delete 或者 update 語句,加個 limit(SQL 后悔藥)
在執行刪除或者更新語句,盡量加上 limit,以下面的這條 SQL 為例吧:
delete from euser where age 30 limit 200;
因為加了 limit 主要有這些好處:
「降低寫錯 SQL 的代價」, 你在命令行執行這個 SQL 的時候,如果不加 limit,執行的時候一個「不小心手抖」,可能數據全刪掉了,如果「刪錯」了呢? 加了 limit 200,就不一樣了。刪錯也只是丟失 200 條數據,可以通過 binlog 日志快速恢復的。
「SQL 效率很可能更高」,你在 SQL 行中,加了 limit 1,如果第一條就命中目標 return,沒有 limit 的話,還會繼續執行掃描表。
「避免了長事務」,delete 執行時, 如果 age 加了索引,MySQL 會將所有相關的行加寫鎖和間隙鎖,所有執行相關行會被鎖住,如果刪除數量大,會直接影響相關業務無法使用。
「數據量大的話,容易把 CPU 打滿」, 如果你刪除數據量很大時,不加 limit 限制一下記錄數,容易把 cpu 打滿,導致越刪越慢的。
3. 設計表的時候,所有表和字段都添加相應的注釋(SQL 規范優雅)
這個好習慣一定要養成啦,設計數據庫表的時候,所有表和字段都添加相應的注釋,后面更容易維護。
「正例:」
CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 主鍵 Id , `name` varchar(255) DEFAULT NULL COMMENT 賬戶名 , `balance` int(11) DEFAULT NULL COMMENT 余額 , `create_time` datetime NOT NULL COMMENT 創建時間 , `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 更新時間 , PRIMARY KEY (`id`), KEY `idx_name` (`name`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT= 賬戶表
「反例:」
CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `balance` int(11) DEFAULT NULL, `create_time` datetime NOT NULL , `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_name` (`name`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8;
4. SQL 書寫格式,關鍵字大小保持一致,使用縮進。(SQL 規范優雅)
「正例:」
SELECT stu.name, sum(stu.score) FROM Student stu WHERE stu.classNo = 1 班 GROUP BY stu.name
「反例:」
SELECT stu.name, sum(stu.score) from Student stu WHERE stu.classNo = 1 班 group by stu.name.
顯然,統一關鍵字大小寫一致,使用縮進對齊,會使你的 SQL 看起來更優雅~
5. INSERT 語句標明對應的字段名稱(SQL 規范優雅)
「反例:」
insert into Student values (666 , 撿田螺的小男孩 , 100
「正例:」
insert into Student(student_id,name,score) values (666 , 撿田螺的小男孩 , 100
6. 變更 SQL 操作先在測試環境執行,寫明詳細的操作步驟以及回滾方案,并在上生產前 review。(SQL 后悔藥)
變更 SQL 操作先在測試環境測試,避免有語法錯誤就放到生產上了。
變更 Sql 操作需要寫明詳細操作步驟,尤其有依賴關系的時候,如:先修改表結構再補充對應的數據。
變更 Sql 操作有回滾方案,并在上生產前,review 對應變更 SQL。
7. 設計數據庫表的時候,加上三個字段:主鍵,create_time,update_time。(SQL 規范優雅)
「反例:」
CREATE TABLE `account` ( `name` varchar(255) DEFAULT NULL COMMENT 賬戶名 , `balance` int(11) DEFAULT NULL COMMENT 余額 , ) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT= 賬戶表
「正例:」
CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 主鍵 Id , `name` varchar(255) DEFAULT NULL COMMENT 賬戶名 , `balance` int(11) DEFAULT NULL COMMENT 余額 , `create_time` datetime NOT NULL COMMENT 創建時間 , `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 更新時間 , PRIMARY KEY (`id`), KEY `idx_name` (`name`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT= 賬戶表
「理由:」
主鍵一般都要加上的,沒有主鍵的表是沒有靈魂的
創建時間和更新時間的話,還是建議加上吧,詳細審計、跟蹤記錄,都是有用的。
阿里開發手冊也提到這個點,如圖
8. 寫完 SQL 語句,檢查 where,order by,group by 后面的列,多表關聯的列是否已加索引,優先考慮組合索引。(SQL 性能優化)
「反例:」
select * from user where address = 深圳 order by age;
「正例:」
添加索引 alter table user add index idx_address_age (address,age)
9. 修改或刪除重要數據前,要先備份,先備份,先備份(SQL 后悔藥)
如果要修改或刪除數據,在執行 SQL 前一定要先備份要修改的數據,萬一誤操作,還能吃口「后悔藥」~
10. where 后面的字段,留意其數據類型的隱式轉換(SQL 性能優化)
「反例:」
//userid 是 varchar 字符串類型 select * from user where userid =123;
「正例:」
select * from user where userid = 123
「理由:」
因為不加單引號時,是字符串跟數字的比較,它們類型不匹配,MySQL 會做隱式的類型轉換,把它們轉換為浮點數再做比較,最后導致索引失效
11. 盡量把所有列定義為 NOT NULL(SQL 規范優雅)
「NOT NULL 列更節省空間」,NULL 列需要一個額外字節作為判斷是否為 NULL 的標志位。
「NULL 列需要注意空指針問題」,NULL 列在計算和比較的時候,需要注意空指針問題。
12. 修改或者刪除 SQL,先寫 WHERE 查一下,確認后再補充 delete 或 update(SQL 后悔藥)
尤其在操作生產的數據時,遇到修改或者刪除的 SQL,先加個 where 查詢一下,確認 OK 之后,再執行 update 或者 delete 操作
13. 減少不必要的字段返回,如使用 select 具體字段 代替 select * (SQL 性能優化)
「反例:」
select * from employee;
「正例:」
select id,name from employee;
理由:
節省資源、減少網絡開銷。
可能用到覆蓋索引,減少回表,提高查詢效率。
14. 所有表必須使用 Innodb 存儲引擎(SQL 規范優雅)
Innodb 「支持事務,支持行級鎖,更好的恢復性」,高并發下性能更好,所以呢,沒有特殊要求 (即 Innodb 無法滿足的功能如:列存儲,存儲空間數據等) 的情況下,所有表必須使用 Innodb 存儲引擎
15. 數據庫和表的字符集盡量統一使用 UTF8(SQL 規范優雅)
盡量統一使用 UTF8 編碼
可以避免亂碼問題
可以避免,不同字符集比較轉換,導致的索引失效問題
「如果需要存儲表情,那么選擇 utf8mb4 來進行存儲,注意它與 utf- 8 編碼的區別。」
16. 盡量使用 varchar 代替 char。(SQL 性能優化)
「反例:」
`deptName` char(100) DEFAULT NULL COMMENT 部門名稱
「正例:」
`deptName` varchar(100) DEFAULT NULL COMMENT 部門名稱
理由:
因為首先變長字段存儲空間小,可以節省存儲空間。
17. 如果修改字段含義或對字段表示的狀態追加時,需要及時更新字段注釋。(SQL 規范優雅)
這個點,是阿里開發手冊中,Mysql 的規約。你的字段,尤其是表示枚舉狀態時,如果含義被修改了,或者狀態追加時,為了后面更好維護,需要即時更新字段的注釋。
18. SQL 命令行修改數據,養成 begin + commit 事務的習慣(SQL 后悔藥)
「正例:」
begin; update account set balance =1000000 where name = 撿田螺的小男孩
commit;
「反例:」
update account set balance =1000000 where name = 撿田螺的小男孩
19. 索引命名要規范,主鍵索引名為 pk_ 字段名; 唯一索引名為 uk _字段名 ; 普通索引名則為 idx _字段名。(SQL 規范優雅)
說明:pk_即 primary key;uk_即 unique key;idx_即 index 的簡稱。
20. WHERE 從句中不對列進行函數轉換和表達式計算
假設 loginTime 加了索引
「反例:」
select userId,loginTime from loginuser where Date_ADD(loginTime,Interval 7 DAY) =now();
「正例:」
explain select userId,loginTime from loginuser where loginTime = Date_ADD(NOW(),INTERVAL - 7 DAY);
「理由:」
索引列上使用 mysql 的內置函數,索引失效
21. 如果修改 / 更新數據過多,考慮批量進行。
反例:
delete from account limit 100000;
正例:
for each(200 次) { delete from account limit 500; }
理由:
大批量操作會會造成主從延遲。
大批量操作會產生大事務,阻塞。
大批量操作,數據量過大,會把 cpu 打滿。
感謝各位的閱讀,以上就是“MySQL 中寫 SQL 的好習慣有哪些”的內容了,經過本文的學習后,相信大家對 MySQL 中寫 SQL 的好習慣有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關知識點的文章,歡迎關注!