MYSQL效能提公升規範

2021-10-13 21:06:31 字數 4074 閱讀 3323

每每在處理資料庫,總會遇到一些效能瓶頸,優化非常棘手,所以需要遵循某些規範,可根據自身業務要求協調以下規範。

【強制】(1) 儲存引擎必須使用innodb

解讀:innodb支援事物、行級鎖、併發效能更好,cpu及記憶體快取頁優化使得資源利用率更高。

【強制】(2)每張表必須設定乙個主鍵id,且這個主鍵id使用自增主鍵(在滿足需要的情況下盡量短),除非在分庫分表環境下。

解讀: 由於innodb組織資料的方式決定了需要有乙個主鍵,而且若是這個主鍵id是單調遞增的可以有效提高插入的效能,避免過多的頁**、減少表碎片提高空間的使用率。 而在分庫分表環境下,則需要統一來分配各個表中的主鍵值,從而避免整個邏輯表中主鍵重複。

【強制】(3)必須使用utf8mb4字符集

解讀:在mysql中的utf-8並非「真正的utf-8」,而utf8mb4」才是真正的「utf-8」

【強制】(4) 資料庫表、表字段必須加入中文注釋

解讀:大家都別懶

【強制】(5) 庫名、表名、欄位名均小寫,下劃線風格,不超過32個字元,必須見名知意,禁止拼音英文混用。

解讀:約定

【強制】(6)單表列數目必須小於30,若超過則應該考慮將表拆分

解讀:單表列數太多使得mysql伺服器處理innodb返回資料之間的對映成本太高

【強制】(7)禁止使用外來鍵,如果有外來鍵完整性約束,需要應用程式控制

【強制】(8)必須把字段定義為not null並且提供預設值

解讀: a、null的列使索引/索引統計/值比較都更加複雜,對mysql來說更難優化 b、null這種型別msql內部需要進行特殊處理,增加資料庫處理記錄的複雜性;同等條件下,表中有較多空字段的時候,資料庫的處理效能會降低很多 c、null值需要更多的儲存空,無論是表還是索引中每行中的null的列都需要額外的空間來標識

【強制】(9)禁用保留字,如desc、range、march等,請參考mysql官方保留字。

【強制】(10)如果儲存的字串長度幾乎相等,使用char定長字串型別。

解讀:能夠減少空間碎片,節省儲存空間。

【建議】(11)在一些場景下,考慮使用timestamp代替datetime。

解讀: a、這兩種型別的都能表達"yyyy-mm-dd hh:mm:ss"格式的時間,timestamp只需要占用4個位元組的長度,可以儲存的範圍為(1970-2038)年,在各個時區,所展示的時間是不一樣的; b、而datetime型別占用8個位元組,對時區不敏感,可以儲存的範圍為(1001-9999)年。

* 【建議】(12)當心自動生成的schema建議所有的schema手動編寫。

解讀:對於一些資料庫客戶端不要太過信任。

【建議】 (1) 為了充分利用快取,不允許使用自定義函式、儲存函式、使用者變數。

解讀: 如果查詢中包含任何使用者自定義函式、儲存函式、使用者變數、臨時表、mysql庫中的系統表,其查詢結果都不會被快取。比如函式now()或者current_date()會因為不同的查詢時間,返回不同的查詢結果。

【強制】(2)在查詢中指定所需的列,而不是直接使用「 *」返回所有的列

解讀: a)讀取不需要的列會增加cpu、io、net消耗 b)不能有效的利用覆蓋索引

【強制】(3)不允許使用屬性隱式轉換

解讀: 假設我們在手機號列上新增了索引,然後執行下面的sql會發生什麼?explain select user_name from parent where phone=13812345678;很明顯就是索引不生效,會全表掃瞄。

【建議】(4)在where條件的屬性上使用函式或者表示式

解讀:mysql無法自動解析這種表示式,無法使用到索引。

【強制】(5)禁止使用外來鍵與級聯,一切外來鍵概念必須在應用層解決。

解讀: 外來鍵與級聯更新適用於單機低併發,不適合分布式、高併發集群;級聯更新是強阻塞,存在資料庫更新風暴的風險;外來鍵影響資料庫的插入速度。

【建議】(6)應盡量避免在where子句中使用or作為連線條件

解讀:根據情況可以選擇使用union all來代替or

【強制】(7)不允許使用%開頭的模糊查詢

解讀:根據索引的最左字首原理,%開頭的模糊查詢無法使用索引,可以使用es來做檢索。

【建議】(1)避免在更新比較頻繁、區分度不高的列上單獨建立索引

解讀: 區分度不高的列單獨建立索引的優化效果很小,但是較為頻繁的更新則會讓索引的維護成本更高

【強制】(2) join的表不允許超過五個。需要join的字段,資料型別必須絕對一致; 多表關聯查詢時,保證被關聯的字段需要有索引。

解讀: 太多表的join會讓mysql的優化器更難權衡出乙個「最佳」的執行計畫(可能性為表數量的階乘),同時要注意關聯欄位的型別、長度、字元編碼等等是否一致。

【強制】(3)在乙個聯合索引中,若第一列索引區分度等於1,那麼則不需要建立聯合索引。

解讀:索引通過第一列就能夠完全定位的資料,所以聯合索引的後邊部分是不需要的。

【強制】(4)建立聯合索引時,必須將區分度更高的字段放在左邊

【建議】(5)利用覆蓋索引來進行查詢操作,避免回表

解讀: 覆蓋查詢即是查詢只需要通過索引即可拿到所需data,而不再需要再次回表查詢,所以效率相對很高。我們在使用explain的結果,extra列會出現:"using index"。這裡也要強調一下不要使用「select * 」,否則幾乎不可能使用到覆蓋索引。

【建議】(6)在較長varchar欄位,例如varchar(100)上建立索引時,應指定索引長度,沒必要對全欄位建立索引,根據實際文字區分度決定索引長度即可。

解讀:索引的長度與區分度是一對矛盾體,一般對字串型別資料,若長度為20的索引,區分度會高達90%以上,則可以考慮建立長度例為20的索引,而非全欄位索引。 例如可以使用select count(distinct left(lesson_code, 20)) / count(*) from lesson;來確定lesson_code字段字元長度為20時文字區分度。

【建議】(7)如果有order by的場景,請注意利用索引的有序性。order by最後的字段是聯合索引的一部分,並且放在索引組合順序的最後,避免出現file_sort的情況,影響查詢效能。

解讀: 1、假設有查詢條件為where a=? and b=? order by c;存在索引:a_b_c,則此時可以利用索引排序。 2、反例:在查詢條件中包含了範圍查詢,那麼索引有序性無法利用,如:where a>10 order by b;索引a_b無法排序。

【建議】(8)在where中索引的列不能某個表示式的一部分,也不能是函式的引數。

解讀:即是某列上已經新增了索引,但是若此列成為表示式的一部分、或者是函式的引數,mysql無法將此列單獨解析出來,索引也不會生效。

【建議】 (9)我們在where條件中使用範圍查詢時,索引最多用於乙個範圍條件,超過乙個則後邊的不走索引。

解讀:mysql能夠使用多個範圍條件裡邊的最左邊的第乙個範圍查詢,但是後邊的範圍查詢則無法使用。

【建議】 (10)在多個表進行外連線時,表之間的關聯字段型別必須完全一致

解讀:當兩個表進行join時,字段型別若沒有完全一致,則加索引也不會生效,這裡的完全一致包括但不限於字段型別、字段長度、字符集、collection等等

使用tcmalloc提公升mysql效能

網上搜到了tcmalloc,說是這個東西可以讓mysql在高併發下效能也很穩定,同時也說了mysql這個問題是因為malloc記憶體分配函式的bug,這個bug會使高併發的mysql效能急劇下降。使用google的tcmalloc 記憶體分配函式代替libc裡的標準malloc.google的開源效...

提公升MySQL查詢效能常用套路

前言 我們查詢資料庫通常會多表關聯,當資料量大時,很多時候我們可以多表查詢分成多次 sql 查詢,來提高效能。如 select from tag join tag post on tag post.tag id tag.id join post on tag post.post id post.id...

MySQL高效能優化規範建議

mysql 提供了兩個方法來處理 ip 位址 inet aton 把 ip 轉為無符號整型 4 8 位 inet ntoa 把整型的 ip 轉為位址 插入資料前,先用 inet aton 把 ip 位址轉為整型,可以節省空間,顯示資料時,使用 inet ntoa 把整型的 ip 位址轉為位址顯示即可...