1. 程式人生 > >MySQL 大表優化方案

MySQL 大表優化方案

當MySQL單表記錄數過大時,增刪改查效能都會急劇下降,可以參考以下步驟來優化:

單表優化

除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題的。而事實上很多時候MySQL單表的效能依然有不少優化空間,甚至能正常支撐千萬級以上的資料量:

欄位

  • 儘量使用TINYINT、SMALLINT、MEDIUM_INT作為整數型別而非INT,如果非負則加上UNSIGNED

  • VARCHAR的長度只分配真正需要的空間

  • 使用列舉或整數代替字串型別

  • 儘量使用TIMESTAMP而非DATETIME,

  • 單表不要有太多欄位,建議在20以內

  • 避免使用NULL欄位,很難查詢優化且佔用額外索引空間

  • 用整型來存IP

索引

  • 索引並不是越多越好,要根據查詢有針對性的建立,考慮在WHERE和ORDER BY命令上涉及的列建立索引,可根據EXPLAIN來檢視是否用了索引還是全表掃描

  • 應儘量避免在WHERE子句中對欄位進行NULL值判斷,否則將導致引擎放棄使用索引而進行全表掃描

  • 值分佈很稀少的欄位不適合建索引,例如”性別”這種只有兩三個值的欄位

  • 字元欄位只建字首索引

  • 字元欄位最好不要做主鍵

  • 不用外來鍵,由程式保證約束

  • 儘量不用UNIQUE,由程式保證約束

  • 使用多列索引時主意順序和查詢條件保持一致,同時刪除不必要的單列索引

查詢SQL

  • 可通過開啟慢查詢日誌來找出較慢的SQL

  • 不做列運算:SELECT id WHERE age + 1 = 10,任何對列的操作都將導致表掃描,它包括資料庫教程函式、計算表示式等等,查詢時要儘可能將操作移至等號右邊

  • sql語句儘可能簡單:一條sql只能在一個cpu運算;大語句拆小語句,減少鎖時間;一條大sql可以堵死整個庫

  • 不用SELECT *

  • OR改寫成IN:OR的效率是n級別,IN的效率是log(n)級別,in的個數建議控制在200以內

  • 不用函式和觸發器,在應用程式實現

  • 避免%xxx式查詢

  • 少用JOIN

  • 使用同類型進行比較,比如用'123'和'123'比,123和123比

  • 儘量避免在WHERE子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描

  • 對於連續數值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5

  • 列表資料不要拿全表,要使用LIMIT來分頁,每頁數量也不要太大

引擎

目前廣泛使用的是MyISAM和InnoDB兩種引擎:

MyISAM

MyISAM引擎是MySQL 5.1及之前版本的預設引擎,它的特點是:

  • 不支援行鎖,讀取時對需要讀到的所有表加鎖,寫入時則對錶加排它鎖

  • 不支援事務

  • 不支援外來鍵

  • 不支援崩潰後的安全恢復

  • 在表有讀取查詢的同時,支援往表中插入新紀錄

  • 支援BLOB和TEXT的前500個字元索引,支援全文索引

  • 支援延遲更新索引,極大提升寫入效能

  • 對於不會進行修改的表,支援壓縮表,極大減少磁碟空間佔用

InnoDB

InnoDB在MySQL 5.5後成為預設索引,它的特點是:

  • 支援行鎖,採用MVCC來支援高併發

  • 支援事務

  • 支援外來鍵

  • 支援崩潰後的安全恢復

  • 不支援全文索引

總體來講,MyISAM適合SELECT密集型的表,而InnoDB適合INSERT和UPDATE密集型的表

系統調優引數

可以使用下面幾個工具來做基準測試:

  • sysbench:一個模組化,跨平臺以及多執行緒的效能測試工具

  • iibench-mysql:基於 Java 的 MySQL/Percona/MariaDB 索引進行插入效能測試工具

  • tpcc-mysql:Percona開發的TPC-C測試工具

具體的調優引數內容較多,具體可參考官方文件,這裡介紹一些比較重要的引數:

  • back_log:back_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆疊中。也就是說,如果MySql的連線資料達到max_connections時,新來的請求將會被存在堆疊中,以等待某一連線釋放資源,該堆疊的數量即back_log,如果等待連線的數量超過back_log,將不被授予連線資源。可以從預設的50升至500

  • wait_timeout:資料庫連線閒置時間,閒置連線會佔用記憶體資源。可以從預設的8小時減到半小時

  • max_user_connection: 最大連線數,預設為0無上限,最好設一個合理上限

  • thread_concurrency:併發執行緒數,設為CPU核數的兩倍

  • skip_name_resolve:禁止對外部連線進行DNS解析,消除DNS解析時間,但需要所有遠端主機用IP訪問

  • key_buffer_size:索引塊的快取大小,增加會提升索引處理速度,對MyISAM表效能影響最大。對於記憶體4G左右,可設為256M或384M,通過查詢show status like 'key_read%',保證key_reads / key_read_requests在0.1%以下最好

  • innodb_buffer_pool_size:快取資料塊和索引塊,對InnoDB表效能影響最大。通過查詢show status like 'Innodb_buffer_pool_read%',保證 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests越高越好

  • innodb_additional_mem_pool_size:InnoDB儲存引擎用來存放資料字典資訊以及一些內部資料結構的記憶體空間大小,當資料庫物件非常多的時候,適當調整該引數的大小以確保所有資料都能存放在記憶體中提高訪問效率,當過小的時候,MySQL會記錄Warning資訊到資料庫的錯誤日誌中,這時就需要該調整這個引數大小

  • innodb_log_buffer_size:InnoDB儲存引擎的事務日誌所使用的緩衝區,一般來說不建議超過32MB

  • query_cache_size:快取MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。當某個表的資料有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的快取資料失效。所以,當我們的資料變化非常頻繁的情況下,使用Query Cache可能會得不償失。根據命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進行調整,一般不建議太大,256MB可能已經差不多了,大型的配置型靜態資料可適當調大.


    可以通過命令show status like 'Qcache_%'檢視目前系統Query catch使用大小

  • read_buffer_size:MySql讀入緩衝區大小。對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會為它分配一段記憶體緩衝區。如果對錶的順序掃描請求非常頻繁,可以通過增加該變數值以及記憶體緩衝區大小提高其效能

  • sort_buffer_size:MySql執行排序使用的緩衝大小。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試增加sort_buffer_size變數的大小

  • read_rnd_buffer_size:MySql的隨機讀緩衝區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀快取區。進行排序查詢時,MySql會首先掃描一遍該緩衝,以避免磁碟搜尋,提高查詢速度,如果需要排序大量資料,可適當調高該值。但MySql會為每個客戶連線發放該緩衝空間,所以應儘量適當設定該值,以避免記憶體開銷過大。

  • record_buffer:每個進行一個順序掃描的執行緒為其掃描的每張表分配這個大小的一個緩衝區。如果你做很多順序掃描,可能想要增加該值

  • thread_cache_size:儲存當前沒有與連線關聯但是準備為後面新的連線服務的執行緒,可以快速響應連線的執行緒請求而無需建立新的

  • table_cache:類似於thread_cache_size,但用來快取表文件,對InnoDB效果不大,主要用於MyISAM

升級硬體

Scale up,這個不多說了,根據MySQL是CPU密集型還是I/O密集型,通過提升CPU和記憶體、使用SSD,都能顯著提升MySQL效能

讀寫分離

也是目前常用的優化,從庫讀主庫寫,一般不要採用雙主或多主引入很多複雜性,儘量採用文中的其他方案來提高效能。同時目前很多拆分的解決方案同時也兼顧考慮了讀寫分離

快取

快取可以發生在這些層次:

  • MySQL內部:在系統調優引數介紹了相關設定

  • 資料訪問層:比如MyBatis針對SQL語句做快取,而Hibernate可以精確到單個記錄,這裡快取的物件主要是持久化物件Persistence Object

  • 應用服務層:這裡可以通過程式設計手段對快取做到更精準的控制和更多的實現策略,這裡快取的物件是資料傳輸物件Data Transfer Object

  • Web層:針對web頁面做快取

  • 瀏覽器客戶端:使用者端的快取

可以根據實際情況在一個層次或多個層次結合加入快取。這裡重點介紹下服務層的快取實現,目前主要有兩種方式:

  • 直寫式(Write Through):在資料寫入資料庫後,同時更新快取,維持資料庫與快取的一致性。這也是當前大多數應用快取框架如Spring Cache的工作方式。這種實現非常簡單,同步好,但效率一般。

  • 回寫式(Write Back):當有資料要寫入資料庫時,只會更新快取,然後非同步批量的將快取資料同步到資料庫上。這種實現比較複雜,需要較多的應用邏輯,同時可能會產生資料庫與快取的不同步,但效率非常高。

表分割槽

MySQL在5.1版引入的分割槽是一種簡單的水平拆分,使用者需要在建表的時候加上分割槽引數,對應用是透明的無需修改程式碼

對使用者來說,分割槽表是一個獨立的邏輯表,但是底層由多個物理子表組成,實現分割槽的程式碼實際上是通過對一組底層表的物件封裝,但對SQL層來說是一個完全封裝底層的黑盒子。MySQL實現分割槽的方式也意味著索引也是按照分割槽的子表定義,沒有全域性索引


使用者的SQL語句是需要針對分割槽表做優化,SQL條件中要帶上分割槽條件的列,從而使查詢定位到少量的分割槽上,否則就會掃描全部分割槽,可以通過EXPLAIN PARTITIONS來檢視某條SQL語句會落在那些分割槽上,從而進行SQL優化,如下圖5條記錄落在兩個分割槽上:

mysqlexplain partitions select count(1)from user_partition where id in(1,2,3,4,5);

+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+

id | select_type | table          | partitions | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |

+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+

|  1 | SIMPLE      | user_partition | p1,p4      | range | PRIMARY       | PRIMARY | 8       | NULL |    5 | Using where;Using index |

+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+

1row inset(0.00sec)

分割槽的好處是:

  • 可以讓單表儲存更多的資料

  • 分割槽表的資料更容易維護,可以通過清楚整個分割槽批量刪除大量資料,也可以增加新的分割槽來支援新插入的資料。另外,還可以對一個獨立分割槽進行優化、檢查、修復等操作

  • 部分查詢能夠從查詢條件確定只落在少數分割槽上,速度會很快

  • 分割槽表的資料還可以分佈在不同的物理裝置上,從而搞笑利用多個硬體裝置

  • 可以使用分割槽表賴避免某些特殊瓶頸,例如InnoDB單個索引的互斥訪問、ext3檔案系統的inode鎖競爭

  • 可以備份和恢復單個分割槽

分割槽的限制和缺點:

  • 一個表最多隻能有1024個分割槽

  • 如果分割槽欄位中有主鍵或者唯一索引的列,那麼所有主鍵列和唯一索引列都必須包含進來

  • 分割槽表無法使用外來鍵約束

  • NULL值會使分割槽過濾無效

  • 所有分割槽必須使用相同的儲存引擎

相關推薦

MySQL優化方案

基於用戶 保存 優先 完成 優化方案 想要 存儲 addition 精確 MySQL大表優化方案 mysql 168 當MySQL單表記錄數過大時,增刪改查性能都會急劇下降,可以參考以下步驟

乾貨!!!MySQL 優化方案(1)

當MySQL單表記錄數過大時,增刪改查效能都會急劇下降,可以參考以下步驟來優化: 單表優化 除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題

優秀後端架構師必會知識:史上最全MySQL優化方案總結

本文原作者“ manong”,原創發表於segmentfault,原文連結:segmentfault.com/a/1190000006158186 1、引言 MySQL作為開源技術的代表作之一,是網際網路得以廣泛流行的重要基礎技術之一。 國外 GitHub、Airbnb、Yelp、

MySQL 優化方案(長文)

當MySQL單表記錄數過大時,增刪改查效能都會急劇下降,可以參考以下步驟來優化:單表優化除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題的。而事實上很多時候MySQL單表的效能依然有不少優

MySQL 優化方案

當MySQL單表記錄數過大時,增刪改查效能都會急劇下降,可以參考以下步驟來優化: 單表優化 除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下

詳解MySQL優化方案

單表優化 除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題的。而事實上很多時候MySQL單表的效能依然有不少優化空間,甚至能正常支撐千萬級以上的資料量:

Mysql資料優化方案

隨著業務規模的不斷擴大,需要選擇合適的方案去應對資料規模的增長,以應對逐漸增長的訪問壓力和資料量。 關於資料庫的擴充套件主要包括:業務拆分、主從複製,資料庫分庫與分表。 (1)業務拆分 假設:Mysql一個數據庫中有三張表,shop表,goods表,history表。

MySQL千萬級優化解決方案

MySQL千萬級大表優化解決方案 非原創,純屬記錄一下。 背景 無意間看到了這篇文章,作者寫的很棒,於是乎,本人自私一把,把乾貨儲存下來。:-) 問題概述 使用阿里雲rds for MySQL資料庫(就是MySQL5.6版本),有個使用者上網記錄表6個月的資料量近2000萬,保留最近一年的資料量達到

MySQL 資料量優化方案

單表優化 除非單表資料未來會一直不斷上漲(例如網路爬蟲),否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度 一般以整型值為主的表在 千萬級以下,字串為主的表在 五百萬以下是沒有太大問題的。而事實上很多時候 MySQL 單表的效能依然有不少優化空間,甚至能正

記錄一次MySQL兩千萬資料的優化解決過程,提供三種解決方案

問題概述 使用阿里雲rds for MySQL資料庫(就是MySQL5.6版本

mysql 分頁查詢 翻頁 優化方案

mysql分頁查詢是先查詢出來所有資料,然後跳過offset,取limit條記錄,造成了越往後的頁數,查詢時間越長 一般優化思路

Mysql千萬級優化

數據庫服務 時間段 系統 時也 導致 slave 如何 1.5 傳統 Mysql的單張表的最大數據存儲量尚沒有定論,一般情況下mysql單表記錄超過千萬以後性能會變得很差。因此,總結一些相關的Mysql千萬級大表的優化策略。 1.優化sql以及索引 1.1優化sql

java面試題之----mysql優化方案

mysql 引擎 它的 易維 range 概述 .com 設置 常用 本文轉載自segmentfault,原文鏈接:https://segmentfault.com/a/1190000006158186。 當MySQL單表記錄數過大時,增刪改查性能都會急劇下降,可以參考以

mysql更新sql的優化策略

    問題sql背景:專案有6個表的要根據pid欄位要寫入對應的brand_id欄位。但是這個其中有兩個表是千萬級別的。我的worker執行之後,線上的mysql主從同步立刻延遲了!運行了一個多小時之

MySql 日常指導,及優化思路

當MySQL單表記錄數過大時,增刪改查效能都會急劇下降 單表優化 除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題的。 而事實上很多時候

Mysql千萬級優化策略

sid 屬於 基於 卡住 行數 arch 行數據 power 基本原理 1.優化sql以及索引 1.1優化sql 1、有索引但未被用到的情況(不建議) (1)避免like的參數以通配符開頭時 盡量避免Like的參數以通配符開頭,否則數據庫引擎會放棄使用索引而進

MySQL 上億優化實踐

原則 優化 順序 lock slave inno -c slow 其它 目錄 背景 分析 select xxx_record語句 delete xxx_record語句

MySQL 在線DML神器--pt-online-schema-change

error 原理 opera ces denied tin reload success lac 一個朋友問我在線對大表進行ddl操作,如何做能盡量避免主從延遲以及不影響在線dml操作呢?我想到一個開源的pt-online-schema-change工具,測試了吧,效果還可

mysql 性能優化方案

說明 mysql的優化 innodb buffer reat iat 緩存命中 isam val 這是一篇關於mysql 性能優化的文章。網上有不少mysql 性能優化方案,不過,mysql的優化同sql server相比,更為麻煩,同樣的設置,在不同的環境下 ,由於內存,

Mysql-索引,優化方案,以及索引失效情況:

宣告一下:下面的優化方案都是基於 “ Mysql-索引-BTree型別 ” 的 一、EXPLAIN 做MySQL優化,我們要善用 EXPLAIN 檢視SQL執行計劃。 下面來個簡單的示例,標註(1,2,3,4,5)我們要重點關注的資料 type列,連線型別。一個好的sql語句至少要達到ran