http://www.reibang.com/p/fd8533b60a74
https://zhuanlan.zhihu.com/p/131467045?from_voters_page=true
MySQL 數(shù)據(jù)庫設(shè)計規(guī)范(存檔)
信仰與初衷關(guān)注
2020.05.28 17:04:04字?jǐn)?shù) 5,761閱讀 4
MySQL 數(shù)據(jù)庫設(shè)計規(guī)范
目錄
1. 規(guī)范背景與目的
MySQL 數(shù)據(jù)庫與 Oracle榄笙、 SQL Server 等數(shù)據(jù)庫相比办斑,有其內(nèi)核上的優(yōu)勢與劣勢。我們在使用 MySQL 數(shù)據(jù)庫的時候需要遵循一定規(guī)范,揚長避短蠕蚜。本規(guī)范旨在幫助或指導(dǎo) RD悔橄、QA、OP 等技術(shù)人員做出適合線上業(yè)務(wù)的數(shù)據(jù)庫設(shè)計挣柬。在數(shù)據(jù)庫變更和處理流程邪蛔、數(shù)據(jù)庫表設(shè)計扎狱、SQL 編寫等方面予以規(guī)范淤击,從而為公司業(yè)務(wù)系統(tǒng)穩(wěn)定、健康地運行提供保障汞贸。
2. 設(shè)計規(guī)范
2.1 數(shù)據(jù)庫設(shè)計
以下所有規(guī)范會按照【高斡』】耳贬、【強制】、【建議】三個級別進(jìn)行標(biāo)注顷蟆,遵守優(yōu)先級從高到低帐偎。
對于不滿足【高位滓伲】和【強制】兩個級別的設(shè)計,DBA 會強制打回要求修改漫贞。
2.1.1 一般命名規(guī)則
【強制】使用小寫迅脐,有助于提高打字速度,避免因大小寫敏感而導(dǎo)致的錯誤豌骏。
【強制】沒有空格窃躲,使用下劃線代替钦睡。
【強制】名稱中沒有數(shù)字赎婚,只有英文字母。
【強制】有效的可理解的名稱纬凤。
【強制】名稱應(yīng)該是自我解釋的撩嚼。
【強制】名稱不應(yīng)超過 32 個字符完丽。
【強制】避免使用前綴逻族。
2.1.2 庫
【強制】遵守以上全部一般命名規(guī)則。
【強制】使用單數(shù)薄辅。
【強制】庫的名稱格式:業(yè)務(wù)系統(tǒng)名稱_子系統(tǒng)名抠璃。
【強制】一般分庫名稱命名格式是庫通配名_編號搏嗡,編號從 0 開始遞增拉一,比如?northwind_001蔚润,以時間進(jìn)行分庫的名稱格式是庫通配名_時間良蛮。
【強制】創(chuàng)建數(shù)據(jù)庫時必須顯式指定字符集决瞳,并且字符集只能是 utf8 或者 utf8mb4左权。創(chuàng)建數(shù)據(jù)庫 SQL 舉例:
createdatabasedb_namedefaultcharactersetutf8;
2.1.3 表
【強制】遵守以上全部一般命名規(guī)則赏迟。
【強制】使用單數(shù)锌杀。
【強制】相關(guān)模塊的表名與表名之間盡量體現(xiàn) join 的關(guān)系,如?user?表和?user_login?表量没。
【強制】創(chuàng)建表時必須顯式指定字符集為 utf8 或 utf8mb4殴蹄。
【強制】創(chuàng)建表時必須顯式指定表存儲引擎類型猾担,如無特殊需求绑嘹,一律為 InnoDB。當(dāng)需要使用除 InnoDB/MyISAM/Memory 以外的存儲引擎時姨丈,必須通過 DBA 審核才能在生產(chǎn)環(huán)境中使用构挤。因為 InnoDB 表支持事務(wù)惕鼓、行鎖、宕機恢復(fù)一膨、MVCC 等關(guān)系型數(shù)據(jù)庫重要特性洒沦,為業(yè)界使用最多的 MySQL 存儲引擎申眼。而這是其它大多數(shù)存儲引擎不具備的括尸,因此首推 InnoDB。
【強制】建表必須有 comment屁柏。
【強制】關(guān)于主鍵:(1) 命名為?id有送,類型為 int 或 bigint雀摘,且為?auto_increment届宠;(2) 標(biāo)識表里每一行主體的字段不要設(shè)為主鍵,建議設(shè)為其它字段如?user_id伤塌,order_id等每聪,并建立?unique key?索引齿风。因為如果設(shè)為主鍵且主鍵值為隨機插入救斑,則會導(dǎo)致 InnoDB 內(nèi)部 page 分裂和大量隨機 I/O,性能下降穷娱。
【建議】核心表(如用戶表泵额,金錢相關(guān)的表)必須有行數(shù)據(jù)的創(chuàng)建時間字段?create_time?和最后更新時間字段?update_time嫁盲,便于排查問題。
【建議】表中所有字段必須都是?NOT NULL?屬性缸托,業(yè)務(wù)可以根據(jù)需要定義?DEFAULT?值嗦董。因為使用?NULL?值會存在每一行都會占用額外存儲空間瘦黑、數(shù)據(jù)遷移容易出錯幸斥、聚合函數(shù)計算結(jié)果偏差等問題甲葬。
【建議】建議對表里的?blob懈贺、text?等大字段梭灿,垂直拆分到其它表里,僅在需要讀這些對象的時候才去 select配乱。
【建議】反范式設(shè)計:把經(jīng)常需要 join 查詢的字段搬泥,在其它表里冗余一份忿檩。如?username?屬性在?user_account爆阶,user_login_log?等表里冗余一份,減少 join 查詢芭碍。
【強制】中間表用于保留中間結(jié)果集窖壕,名稱必須以?tmp_?開頭杉女。備份表用于備份或抓取源表快照熏挎,名稱必須以?bak_?開頭坎拐。中間表和備份表定期清理。
【強制】對于超過 100W 行的大表進(jìn)行?alter table都伪,必須經(jīng)過 DBA 審核陨晶,并在業(yè)務(wù)低峰期執(zhí)行先誉。因為?alter table?會產(chǎn)生表鎖的烁,期間阻塞對于該表的所有寫入撮躁,對于業(yè)務(wù)可能會產(chǎn)生極大影響把曼。
2.1.4 字段
【強制】遵守以上全部一般命名規(guī)則。
【建議】盡可能選擇短的或一兩個單詞注盈。
【強制】避免使用保留字作為字段名稱:order老客,date胧砰,name?是數(shù)據(jù)庫的保留字,避免使用它偿乖√靶剑可以為這些名稱添加前綴使其易于理解画切,如?user_name囱怕,signup_date?等。
【強制】避免使用與表名相同的字段名娃弓,這會在編寫查詢時造成混淆庞萍。
【強制】在數(shù)據(jù)庫模式上定義外鍵。
【強制】避免使用縮寫或基于首字母縮寫詞的名稱忘闻。
【強制】外鍵列必須具有表名及其主鍵,例如:blog_id?表示來自表博客的外鍵 id恋博。
2.1.5 字段數(shù)據(jù)類型優(yōu)化
【建議】表中的自增列(auto_increment?屬性)齐佳,推薦使用?bigint?類型。因為無符號?int?存儲范圍為?0~4,294,967,295(不到 43 億)债沮,溢出后會導(dǎo)致報錯。
【建議】業(yè)務(wù)中選擇性很少的狀態(tài)?status疫衩、類型?type?等字段推薦使用?tinytint?或者?smallint?類型節(jié)省存儲空間硅蹦。
【建議】業(yè)務(wù)中 IP 地址字段推薦使用?int?類型,不推薦用?char(15)闷煤。因為?int?只占 4 字節(jié)童芹,可以用如下函數(shù)相互轉(zhuǎn)換,而?char(15)?占用至少 15 字節(jié)鲤拿。
SQL:
selectinet_aton('192.168.2.12');selectinet_ntoa(3232236044);
PHP:
ip2long('192.168.2.12');long2ip(3530427185);
Java:
publicstaticlongipToLong(Stringaddr){String[]addrArray=addr.split("\\.");longnum=0;for(inti=0;i<addrArray.length;i++){intpower=3-i;num+=((Integer.parseInt(addrArray[i])%256*Math.pow(256,power)));}returnnum;}publicstaticStringlongToIp(longi){return((i>>24)&0xFF)+"."+((i>>16)&0xFF)+"."+((i>>8)&0xFF)+"."+(i&0xFF);}
【建議】不推薦使用?enum假褪,set。 因為它們浪費空間近顷,且枚舉值寫死了生音,變更不方便宁否。推薦使用?tinyint?或?smallint。
【建議】不推薦使用?blob缀遍,text?等類型慕匠。它們都比較浪費硬盤和內(nèi)存空間。在加載表數(shù)據(jù)時域醇,會讀取大字段到內(nèi)存里從而浪費內(nèi)存空間台谊,影響系統(tǒng)性能。建議和 PM歹苦、RD 溝通青伤,是否真的需要這么大字段。InnoDB 中當(dāng)一行記錄超過 8098 字節(jié)時殴瘦,會將該記錄中選取最長的一個字段將其 768 字節(jié)放在原始 page 里狠角,該字段余下內(nèi)容放在?overflow-page?里。不幸的是在?compact?行格式下蚪腋,原始?page?和?overflow-page?都會加載丰歌。
【建議】存儲金錢的字段,建議用?int?以分為單位存儲屉凯,最大數(shù)值約 4290 萬立帖,程序端乘以 100 和除以 100 進(jìn)行存取。因為?int?占用 4 字節(jié)悠砚,而?double?占用8字節(jié)晓勇,空間浪費。
【建議】文本數(shù)據(jù)盡量用?varchar?存儲灌旧。因為?varchar?是變長存儲绑咱,比?char?更省空間。MySQL server 層規(guī)定一行所有文本最多存 65535 字節(jié)枢泰,因此在 utf8 字符集下最多存 21844 個字符描融,超過會自動轉(zhuǎn)換為?mediumtext?字段。而?text?在 utf8 字符集下最多存 21844 個字符衡蚂,mediumtext?最多存 2^24/3 個字符窿克,longtext?最多存 2^32 個字符。一般建議用?varchar?類型毛甲,字符數(shù)不要超過 2700年叮。
【建議】時間類型盡量選取?timestamp。因為?datetime?占用 8 字節(jié)玻募,timestamp?僅占用4字節(jié)谋右,但是范圍為?1970-01-01 00:00:01?到?2038-01-01 00:00:00。更為高階的方法补箍,選用?int?來存儲時間改执,使用 SQL 函數(shù)?unix_timestamp()?和?from_unixtime()?來進(jìn)行轉(zhuǎn)換啸蜜。
詳細(xì)存儲大小參考下圖:
類型(同義詞)存儲長度(BYTES)最小值(SIGNED/UNSIGNED)最大值(SIGNED/UNSIGNED)
整形數(shù)字
TINYINT1-128/0127/255
SMALLINT2-32,768/032767/65,535
MEDIUMINT3-8,388,608/08388607/16,777,215/
INT(INTEGER)4-2,14,7483,648/02147483647/4,294,967,295/
BIGINT8-2^63/0263-1/264-1
小數(shù)支持
FLOAT[(M[,D])]4 or 8-
DOUBLE[(M[,D])]
(REAL, DOUBLE PRECISION)
8-
時間類型
DATETIME81001-01-01 00:00:009999-12-31 23:59:59
DATE31001-01-019999-12-31
TIME300:00:0023:59:59
YEAR110019999
TIMESTAMP41970-01-01 00:00:00
2.1.6 索引設(shè)計
【強制】InnoDB 表必須主鍵為?id int/bigint auto_increment,且主鍵值禁止被更新辈挂。
【建議】主鍵的名稱以?pk_?開頭衬横,唯一鍵以?uk_?開頭,普通索引以?ix_?開頭终蒂,一律使用小寫格式蜂林,以表名/字段的名稱或縮寫作為后綴。
【強制】InnoDB 和 MyISAM 存儲引擎表拇泣,索引類型必須為?BTREE噪叙;MEMORY 表可以根據(jù)需要選擇?HASH?或者?BTREE?類型索引。
【強制】單個索引中每個索引記錄的長度不能超過 64KB霉翔。
【建議】單個表上的索引個數(shù)不能超過 7 個睁蕾。
【建議】在建立索引時,多考慮建立聯(lián)合索引债朵,并把區(qū)分度最高的字段放在最前面子眶。如列?user_id?的區(qū)分度可由?select count(distinct user_id)?計算出來。
【建議】在多表 join 的 SQL 里序芦,保證被驅(qū)動表的連接列上有索引臭杰,這樣 join 執(zhí)行效率最高。
【建議】建表或加索引時谚中,保證表里互相不存在冗余索引渴杆。對于 MySQL 來說,如果表里已經(jīng)存在?key(a, b)宪塔,則?key(a)?為冗余索引将塑,需要刪除。
【建議】如果選擇性超過 20%蝌麸,那么全表掃描比使用索引性能更優(yōu),即沒有設(shè)置索引的必要艾疟。
2.1.7 分庫分表来吩、分區(qū)表
【強制】分區(qū)表的分區(qū)字段(partition-key)必須有索引,或者是組合索引的首列蔽莱。
【強制】單個分區(qū)表中的分區(qū)(包括子分區(qū))個數(shù)不能超過 1024弟疆。
【強制】上線前 RD 或者 DBA 必須指定分區(qū)表的創(chuàng)建、清理策略盗冷。
【強制】訪問分區(qū)表的 SQL 必須包含分區(qū)鍵怠苔。
【建議】單個分區(qū)文件不超過 2G,總大小不超過 50G仪糖。建議總分區(qū)數(shù)不超過 20 個柑司。
【強制】對于分區(qū)表執(zhí)行?alter table?操作迫肖,必須在業(yè)務(wù)低峰期執(zhí)行。
【強制】采用分庫策略的攒驰,庫的數(shù)量不能超過 1024蟆湖。
【強制】采用分表策略的,表的數(shù)量不能超過 4096玻粪。
【建議】單個分表不超過 500W 行隅津,ibd 文件大小不超過 2G,這樣才能讓數(shù)據(jù)分布式變得性能更佳劲室。
【建議】水平分表盡量用取模方式伦仍,日志、報表類數(shù)據(jù)建議采用日期進(jìn)行分表很洋。
2.1.8 字符集
【強制】數(shù)據(jù)庫本身庫充蓝、表、列所有字符集必須保持一致蹲缠,為?utf8?或?utf8mb4棺克。
【強制】前端程序字符集或者環(huán)境變量中的字符集,與數(shù)據(jù)庫线定、表的字符集必須一致娜谊,統(tǒng)一為?utf8。
2.1.9 程序?qū)?DAO 設(shè)計建議
【建議】新的代碼不要用 model斤讥,推薦使用手動拼 SQL + 綁定變量傳入?yún)?shù)的方式纱皆。因為 model 雖然可以使用面向?qū)ο蟮姆绞讲僮?db,但是其使用不當(dāng)很容易造成生成的 SQL 非常復(fù)雜芭商,且 model 層自己做的強制類型轉(zhuǎn)換性能較差派草,最終導(dǎo)致數(shù)據(jù)庫性能下降。
【建議】前端程序連接 MySQL 或者 Redis铛楣,必須要有連接超時和失敗重連機制近迁,且失敗重試必須有間隔時間。
【建議】前端程序報錯里盡量能夠提示 MySQL 或 Redis 原生態(tài)的報錯信息簸州,便于排查錯誤鉴竭。
【建議】對于有連接池的前端程序,必須根據(jù)業(yè)務(wù)需要配置初始岸浑、最小搏存、最大連接數(shù),超時時間以及連接回收機制矢洲,否則會耗盡數(shù)據(jù)庫連接資源璧眠,造成線上事故。
【建議】對于?log?或?history?類型的表,隨時間增長容易越來越大责静,因此上線前 RD 或者 DBA 必須建立表數(shù)據(jù)清理或歸檔方案袁滥。
【建議】在應(yīng)用程序設(shè)計階段,RD 必須考慮并規(guī)避數(shù)據(jù)庫中主從延遲對于業(yè)務(wù)的影響泰演。盡量避免從庫短時延遲(20 秒以內(nèi))對業(yè)務(wù)造成影響呻拌,建議強制一致性的讀開啟事務(wù)走主庫,或更新后過一段時間再去讀從庫睦焕。
【建議】多個并發(fā)業(yè)務(wù)邏輯訪問同一塊數(shù)據(jù)(InnoDB 表)時藐握,會在數(shù)據(jù)庫端產(chǎn)生行鎖甚至表鎖導(dǎo)致并發(fā)下降,因此建議更新類 SQL 盡量基于主鍵去更新垃喊。
【建議】業(yè)務(wù)邏輯之間加鎖順序盡量保持一致猾普,否則會導(dǎo)致死鎖。
【建議】對于單表讀寫比大于 10:1 的數(shù)據(jù)行或單個列本谜,可以將熱點數(shù)據(jù)放在緩存里(如 Memcached 或 Redis)初家,加快訪問速度,降低 MySQL 壓力乌助。
2.1.10 一個規(guī)范的建表語句示例
一個較為規(guī)范的建表語句為:
createtableuser(`id`bigint(11)notnullauto_increment,`user_id`bigint(11)notnullcomment'用戶 ID',`username`varchar(45)notnullcomment'登錄名',`email`varchar(30)notnullcomment'郵箱',`nickname`varchar(45)notnullcomment'昵稱',`avatar`int(11)notnullcomment'頭像',`birthday`datenotnullcomment'生日',`gender`tinyint(4)default'0'comment'性別',`intro`varchar(150)defaultnullcomment'簡介',`resume_url`varchar(300)notnullcomment'簡歷存放地址',`register_ip`intnotnullcomment'用戶注冊時的源 IP',`review_status`tinyintnotnullcomment'審核狀態(tài)溜在,1-通過,2-審核中他托,3-未通過掖肋,4-尚未提交審核',`create_time`timestampnotnullcomment'記錄創(chuàng)建的時間',`update_time`timestampnotnullcomment'資料修改的時間',primarykey(`id`),uniquekey`idx_user_id`(`user_id`),key`idx_username`(`username`),key`idx_create_time`(`create_time`,`review_status`))engine=InnoDBdefaultcharset=utf8comment='用戶基本信息';
2.2 SQL 編寫
2.2.1 DML 語句
【強制】select 語句必須指定具體字段名稱,禁止寫成?*赏参。因為?select *?會將不該讀的數(shù)據(jù)也從 MySQL 里讀出來志笼,造成網(wǎng)卡壓力。
【強制】insert 語句指定具體字段名稱把篓,不要寫成?insert into t1 values(…)纫溃,道理同上。
【建議】insert into … values(xx),(xx),(xx)…韧掩,這里 xx 的值不要超過 5000 個紊浩。值過多雖然上線很快,但會引起主從同步延遲疗锐。
【建議】select 語句不要使用?union坊谁,推薦使用?union all,并且?union?子句個數(shù)限制在 5 個以內(nèi)窒悔。因為?union all?不需要去重,節(jié)省數(shù)據(jù)庫資源敌买,提高性能简珠。
【建議】in 值列表限制在 500 以內(nèi)。例如?select … where user_id in(…500 個以內(nèi)…)聋庵,這么做是為了減少底層掃描膘融,減輕數(shù)據(jù)庫壓力從而加速查詢。
【建議】事務(wù)里批量更新數(shù)據(jù)需要控制數(shù)量祭玉,進(jìn)行必要的 sleep氧映,做到少量多次。
【強制】事務(wù)涉及的表必須全部是 InnoDB 表脱货。否則一旦失敗不會全部回滾岛都,且易造成主從庫同步終端。
【強制】寫入和事務(wù)發(fā)往主庫振峻,只讀 SQL 發(fā)往從庫臼疫。
【強制】除靜態(tài)表或小表(100 行以內(nèi)),dml 語句必須有 where 條件扣孟,且使用索引查找烫堤。
【強制】生產(chǎn)環(huán)境禁止使用?hint,如?sql_no_cache凤价,force index鸽斟,ignore key,straight join?等利诺。因為?hint?是用來強制 sql 按照某個執(zhí)行計劃來執(zhí)行富蓄,但隨著數(shù)據(jù)量變化我們無法保證自己當(dāng)初的預(yù)判是正確的,因此我們要相信 MySQL 優(yōu)化器立轧。
【強制】where 條件里等號左右字段類型必須一致格粪,否則無法利用索引。
【建議】select|update|delete|replace?要有 where 子句氛改,且 where 子句的條件必需使用索引查找帐萎。
【強制】生產(chǎn)數(shù)據(jù)庫中強烈不推薦大表上發(fā)生全表掃描,但對于 100 行以下的靜態(tài)表可以全表掃描胜卤。查詢數(shù)據(jù)量不要超過表行數(shù)的 25%疆导,否則不會利用索引。
【強制】where 子句中禁止只使用全模糊的 like 條件進(jìn)行查找葛躏,必須有其它等值或范圍查詢條件澈段,否則無法利用索引。
【建議】索引列不要使用函數(shù)或表達(dá)式舰攒,否則無法利用索引败富。如?where length(name) = 'admin'?或?where user_id + 2 = 10023。
【建議】減少使用 or 語句摩窃,可將 or 語句優(yōu)化為 union兽叮,然后在各個 where 條件上建立索引芬骄。如?where a = 1 or b = 2?優(yōu)化為?where a = 1 … union … where b = 2, key(a), key(b)。
【建議】分頁查詢鹦聪,當(dāng)?limit?起點較高時账阻,可先用過濾條件進(jìn)行過濾。如?select a, b, c from t1 limit 10000, 20;?優(yōu)化為:?select a, b, c from t1 where id > 10000 limit 20;泽本。
2.2.2 多表連接
【強制】禁止跨 DB 的 join 語句淘太。因為這樣可以減少模塊間耦合,為數(shù)據(jù)庫拆分奠定堅實基礎(chǔ)规丽。
【強制】禁止在業(yè)務(wù)的更新類 SQL 語句中使用 join蒲牧,比如?update t1 join t2 …。
【建議】不建議使用子查詢嘁捷,建議將子查詢 SQL 拆開結(jié)合程序多次查詢造成,或使用 join 來代替子查詢。
【建議】線上環(huán)境雄嚣,多表 join 不要超過 3 個表晒屎。
【建議】多表連接查詢推薦使用別名,且 select 列表中要用別名引用字段缓升,數(shù)據(jù)庫.表格式鼓鲁,如?select a from db1.table1 alias1 where …。
【建議】在多表 join 中港谊,盡量選取結(jié)果集較小的表作為驅(qū)動表骇吭,來 join 其它表。
2.2.3 事務(wù)
【建議】事務(wù)中?insert|update|delete|replace?語句操作的行數(shù)控制在 2000 以內(nèi)歧寺,以及 where 子句中 in 列表的傳參個數(shù)控制在 500 以內(nèi)燥狰。
【建議】批量操作數(shù)據(jù)時,需要控制事務(wù)處理間隔時間斜筐,進(jìn)行必要的 sleep龙致,一般建議值 5-10 秒。
【建議】對于有?auto_increment?屬性字段的表的插入操作顷链,并發(fā)需要控制在 200 以內(nèi)目代。
【強制】程序設(shè)計必須考慮“數(shù)據(jù)庫事務(wù)隔離級別”帶來的影響,包括臟讀嗤练、不可重復(fù)讀和幻讀榛了。線上建議事務(wù)隔離級別為?repeatable-read。
【建議】事務(wù)里包含 SQL 不超過 5 個(支付業(yè)務(wù)除外)煞抬。因為過長的事務(wù)會導(dǎo)致鎖數(shù)據(jù)較久霜大,MySQL 內(nèi)部緩存、連接消耗過多等雪崩問題革答。
【建議】事務(wù)里更新語句盡量基于主鍵或?unique key战坤,如?update … where id = XX;遮婶,否則會產(chǎn)生間隙鎖,內(nèi)部擴大鎖定范圍湖笨,導(dǎo)致系統(tǒng)性能下降,產(chǎn)生死鎖蹦骑。
【建議】盡量把一些典型外部調(diào)用移出事務(wù)慈省,如調(diào)用 Web Service,訪問文件存儲等眠菇,從而避免事務(wù)過長边败。
【建議】對于 MySQL 主從延遲嚴(yán)格敏感的 select 語句,請開啟事務(wù)強制訪問主庫捎废。
2.2.4 排序和分組
【建議】減少使用?order by笑窜,和業(yè)務(wù)溝通能不排序就不排序,或?qū)⑴判蚍诺匠绦蚨巳プ龅橇啤rder by排截、group by、distinct?這些語句較為耗費 CPU辐益,數(shù)據(jù)庫的 CPU 資源是極其寶貴的断傲。
【建議】order by、group by智政、distinct?這些 SQL 盡量利用索引直接檢索出排序好的數(shù)據(jù)认罩。如?where a = 1 order by?可以利用?key(a, b)。
【建議】包含了?order by续捂、group by垦垂、distinct?這些查詢的語句,where 條件過濾出來的結(jié)果集請保持在 1000 行以內(nèi)牙瓢,否則 SQL 會很慢劫拗。
2.2.5 線上禁止使用的 SQL 語句
【高危】禁用?update|delete t1 … where a = XX limit XX;?這種帶 limit 的更新語句一罩。因為會導(dǎo)致主從不一致杨幼,導(dǎo)致數(shù)據(jù)錯亂。建議加上?order by PK聂渊。
【高尾罟海】禁止使用關(guān)聯(lián)子查詢,如?update t1 set … where name in(select name from user where …);汉嗽,效率極其低下欲逃。
【強制】禁用 procedure、function饼暑、trigger稳析、views洗做、event、外鍵約束彰居。因為他們消耗數(shù)據(jù)庫資源诚纸,降低數(shù)據(jù)庫實例可擴展性。推薦都在程序端實現(xiàn)陈惰。
【強制】禁用?insert into … on duplicate key update …?在高并發(fā)環(huán)境下畦徘,會造成主從不一致。
【強制】禁止聯(lián)表更新語句抬闯,如?update t1, t2 where t1.id = t2.id …井辆。