MySQL 建表規範 以及注意

參考 Alibaba  P3C 規範文檔  git

https://github.com/alibaba/p3c/blob/master/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%EF%BC%88%E8%AF%A6%E5%B0%BD%E7%89%88%EF%BC%89.pdfgithub

 

  1. 建表規範

        1).在使用判斷是否的狀況下,使用 is_xxx的命名,而且數據類型是unsigned tinyint(1表示爲真 0表示爲假)。sql

        2).全部的表的代表必須以小寫字母+數字(windows不分大小寫,Linux分大小寫),且兩個下劃線中間不出現數字(錯誤:table1_3_system)。windows

        3).以單數形式寫表名,不要使用desc,range,match,delayed等MySQL保留字段,索引名稱規範爲:性能優化

pk_xx 表示primary key(主鍵索引); uk_xx表示unique key (惟一索引);idx_xx表普通索引併發

        4).小數使用 decimal ,能夠定義經常使用的如價格,工資,匯款等等。分佈式

        5).長度(0-255) 且長度基本一致的使用char,長度(0-5000)不預先設置存儲空間的,可使用varchar,但長度大於5000,則使用text來處理,而且新建一張表來存儲,以主鍵綁定,避免影響其餘字段索引的效率。性能

        6).一個表必備的三個字段,id,gmt_create,gmt_modified,id表主鍵應該是無符號的,能夠是int或bigint,後面兩個爲datetime類型,前者表示建立時間,後者表示被動修改時間優化

        7).命名規範,通常以「業務名_功能名」,庫名應當和應用名稱一致。搜索引擎

        8).表是容許適當的冗餘,這樣提升查詢速度,當數據大時,效果很明顯。但也須要注意,應當是不頻繁變化的字段,且不該該是varchar超長字符,更不宜是text文本。

        9).單表內容超過500W行或者存儲大於2GB,才推薦分庫分表,若是預計三年內達不到該值,在設計是能夠不考慮分庫分表。

        10).適當的字符存儲長度,不但節約存儲空間,節約索引存儲,同時提高了檢索的速度。  

            

     2.索引

        1).業務上具備惟一特性的字段,便是是組合也應當建成惟一索引。(不要覺得惟一索引影響insert的速度,其實能夠忽略,與之相比帶來的查詢速度是很是大的,另外,在應用層便是是作了數據的校驗,可是隻要是沒有惟一的索引,根據墨菲定律,必然產生髒數據。)

        2).超過三個表禁止使用join。須要使用join的須要注意索引與sql性能,同時數據類型須要一致。多表關聯查詢時,須要保證被關聯的字段設置了索引。

        3).爲varchar設置索引須要指定其長度,不必對全文本進行索引創建,通常在20長度區分度在90%以上,可使用count(distinct left(列名,索引長度))/count(*)的區分度來判斷。

        4).頁面搜索禁用左模糊和全模糊,若是須要則使用搜索引擎。索引文件具備B-Tree的最左前綴匹配特性,若是左邊未肯定則不能使用該索引。

        5).若是與有order by 的場景,請注意利用索引的有序性。order by最後的字段是組合索引的一部分,請別放到組合索引的最後,避免出現file_sort,影響查詢性能。如: where a = ? b = ? order by c; 索引爲:a_b_c. 當索引中有範圍查找,那麼沒法利用有序性。如 where a > 10 order by b; 索引爲 a_b.

        6).利用覆蓋索引進行查詢。用explain的結果,extra列會出現:using index.

        7).利用延遲關聯或子查詢優化超多分頁場景。也就是先定位查詢值,再聯合查詢。

如: select a.* from table1 as a ,(select id from table2  where 條件 limit 1000,100)as b where a.id =b.id

        8).SQL 性能優化目標:至少是range級別,要求是ref級別,若是能夠的話應當是consts.

            consts : 只有一條匹配數據(主鍵或者惟一索引)

            ref: 指的是使用普通的索引查詢

            range: 對索引進行範圍搜索

       9). 創建的組合索引,區分度最高的查詢在左邊。

        若是: where a=? b=?,a列基本上能區分出惟一值,那麼只須要創建a的索引就能夠。

說明: 存在等號和非等號的查詢狀況下,在建索引的時候,請把等號的前置。如:where a =? and b =? 便是a的區分度更高,也須要把b放在前面,即uk_b_a;

     10).防止因字段類型不一樣,形成隱式的轉換,致使索引失效。

     11).極端

            寧濫勿缺 : 認爲一個查詢就須要一個索引。

            寧缺毋濫: 認爲索引會消耗控件,嚴重拖慢更新和新增的速度

            抵制惟一索引:認爲業務的惟一性一概經過應用層檢查,並經過」先查後插」方式解決。

   3. SQL語句

        1). 不要使用count(列名) 或者count(1) 來替代count(*),count(*)是sql定義的用來統計的標準語法。count(* )會統計值爲NULL的行,可是count(列名) 不會統計。

        2).count(distinct col) 計算該列值非NULL且非重複的行,count(distinct  col1,col2)若是第一列值爲空,那麼便是另外一列有不一樣的值,也是返回0.

        3).須要注意的一個問題是count(*)未找到行是返回0,而sum(col)則是返回NULL,所以會出現NPE。可使用 select if(ISNULL(sum(g)),0,sum(g)) from table.

         4).ISNULL()是判斷是否爲NULL,null與任何值比較都是null,而不是true 或者false。

         5).當count(*)=0 時,應當結束掉後面須要分頁的操做。

         6).不使用外鍵與級聯。一切外鍵概念須要在應用層解決。

            以學生表和成績表爲例,學生表的student_id是主鍵,而成績表中的student_id則爲外鍵。在更新學生表時,同時須要更新成績表,那麼這是一個級聯的更新。外鍵,級聯是單機低併發,不適合分佈式,並有影響數據更新,影響插入性能。

         7).不使用存儲過程。

         8).數據修好時,須要先select,在刪除。

         9).in儘可能不使用,若是須要使用則須要控制in後面的數量爲1000個之內。

相關文章
相關標籤/搜索