mysql資料庫優化(三)--分割槽
mysql的分割槽,分表
分割槽:把一個數據表的檔案和索引分散儲存在不同的物理檔案中。 特點:業務層透明,無需任何修改,即使從新分表,也是在mysql層進行更改(業務層程式碼不動)
分表:把原來的表根據條件分成多個表,如原來的表為 user;現在分成2個小表 user_1,user_2; 特點:業務層需要修改程式碼。如過業務改變,可能需要從新分表,導致維護困難
當資料量達到一定級別後,需要通過 分割槽或分表來提高使用者體驗
如下知識點 為 分割槽
如:現在生產環境有使用者表 account_user,對其按照 日期(每季度)進行分割槽。
表結構如下:
輸入命令:show create table account_user;
由於此表有 主鍵和unique鍵,在分割槽時,必須要求被用來匹配分割槽的欄位被包含在 主鍵,和unique鍵中(也就是複合主鍵和複合unique鍵);
通過如下命令進行操作把 create_time分別放在主鍵和unique鍵中 (這時mobile欄位不能保證唯一性,這是個大問題,需要解決)
新增unique鍵: ALTER TABLE account_user ADD UNIQUE KEY (mobile,create_time);
刪除unique鍵: ALTER TABLE account_user DROP UNIQUE KEY ;
新增主鍵:ALTER TABLE account_user ADD PRIMARY KEY (id,create_time);
刪除主鍵:ALTER TABLE account_user DROP PRIMARY KEY;
然後根據官網教程:
如下根據range分割槽進行新增:
ALTER TABLE account_user PARTITION BY RANGE (TO_DAYS(create_time)) ( PARTITION account_user_2018_01 VALUES less than (TO_DAYS('2018-01-01')), PARTITION account_user_2018_04 VALUES less than (TO_DAYS('2018-04-01')), PARTITION account_user_2018_07 VALUES less than (TO_DAYS('2018-07-01')), PARTITION account_user_2018_10 VALUES less than (TO_DAYS('2018-10-01')), PARTITION account_user_2018_more VALUES less than MAXVALUE )
然後檢視 結果:
驗證分割槽效果:
優點:根據create_time進行範圍查詢,會使用分割槽,避免全表掃描
使用分割槽的情況下:
只是查詢了 3351行,或者說是查詢了 (account_user_2018_01,account_user_2018_04,account_user_2018_07)三個分割槽
在沒有分割槽的情況下:
發現進行全表掃描,行數為46808行
相關操作:
檢視行資料所在分割槽:SELECT * FROM account_user PARTITION (account_user_2018_07) WHERE id=1;
增加分割槽: ALTER TABLE account_user ADD PARTITION ( PARTITION account_user_2019_01 VALUES LESS THAN (TO_DAYS('2019-01-01')) ) ; 如果對應range分割槽有 MAXVALUE ,要先刪除,否則報錯
刪除分割槽: ALTER TABLE account_user DROP PARTITION account_user_2019_01 ;
刪除分割槽資料:ALTER TABLE account_user TRUNCATE PARTITION account_user_2019_01,account_user_2019_04;
rebuild重建分割槽:ALTER TABLE account_user REBUILD PARTITION account_user_2019_01 ; #相當於 drop所有記錄,然後再reinsert;可以解決磁碟碎片
優化分割槽:ALTER TABLE account_user OPTIMIZE PARTITION account_user_2019_01 ; #在刪除資料後回收空間和碎片整理
analzye分割槽:ALTER TABLE account_user ANALZYE PARTITION account_user_2019_01 ;
check分割槽:ALTER TABLE account_user CHECK PARTITION account_user_2019_01 ;
所有分割槽方式:
list: 每個分割槽的定義和選擇是基於某列的值從屬於一個值列表集中的一個值. 將要匹配的任何值都必須在值列表中找到。
如:
ALTER TABLE account_user PARTITION BY LIST (TO_DAYS(create_time)) ( PARTITION account_user_2018_01 VALUES IN (TO_DAYS('2018-01-01'),TO_DAYS('2018-01-02')), PARTITION account_user_2018_04 VALUES IN (TO_DAYS('2018-01-03'),TO_DAYS('2018-01-04')) )
range:每個分割槽包含那些分割槽表示式的值位於一個給定的連續區間內的行
如:
ALTER TABLE account_user PARTITION BY RANGE (TO_DAYS(create_time)) ( PARTITION account_user_2018_01 VALUES less than (TO_DAYS('2018-01-01')), PARTITION account_user_2018_04 VALUES less than (TO_DAYS('2018-04-01')), PARTITION account_user_2018_07 VALUES less than (TO_DAYS('2018-07-01')), PARTITION account_user_2018_10 VALUES less than (TO_DAYS('2018-10-01')), PARTITION account_user_2018_more VALUES less than MAXVALUE )
在使用 範圍查詢 create_time 時,會使用分割槽進行查詢(時間複雜度:O(log N)),所有速度比沒有使用分割槽(時間複雜度:O(N))的快。
hash:無需定義分割槽的條件,資料會平均分配到每個分割槽。只需要指明分割槽數即可。
如:
ALTER TABLE account_user PARTITION BY HASH(TO_DAYS(create_time)) PARTITIONS 5
LINEAR HASH分割槽:在資料量大的場景,譬如TB級,增加、刪除、合併和拆分分割槽會更快,缺點是,相對於HASH分割槽,它資料分佈不均勻的概率更大。
ALTER TABLE account_user PARTITION BY LINEAR HASH(TO_DAYS(create_time)) PARTITIONS 5
key分割槽:
1. KEY分割槽允許多列,而HASH分割槽只允許一列。
2. 如果在有主鍵或者唯一鍵的情況下,key中分割槽列可不指定,預設為主鍵或者唯一鍵,如果沒有,則必須顯性指定列。
3. KEY分割槽物件必須為列,而不能是基於列的表示式。
4. KEY分割槽和HASH分割槽的演算法不一樣,PARTITION BY HASH (expr),MOD取值的物件是expr返回的值,而PARTITION BY KEY (column_list),基於的是列的MD5值。
分割槽優點:
分割槽可以分在多個磁碟,儲存更大一點
根據查詢條件,也就是where後面的條件,查詢只查詢相應的分割槽不用全部查找了
進行大資料搜尋時可以進行並行處理。
跨多個磁碟來分散資料查詢,來獲得更大的查詢吞吐量
分割槽缺點:
其 分割槽對應的key必須包含主鍵或者unique鍵,導致 unique 鍵的欄位失效(如使用者登錄檔,手機號唯一性)
需要仔細考慮評估業務系統 對錶 進行操作的側重點,然後選擇欄位和分割槽方式進行分割槽,儘量平均分配資料到每個分割槽。分割槽後進行相關驗證性測試 是否有效果
案例:
1.公司通過推薦註冊可以提現紅包的方式拉取使用者,造成 其他人利用介面惡意註冊殭屍使用者,導致使用者表資料量過多,影響正常使用者的使用。需求:活躍使用者只有總使用者的5%,如何提高活躍使用者的體驗?
方案:
1.在 使用者表中增加一個 代表活躍度的欄位,在使用者每次活躍後,其值相應增加。通過 分割槽的方式(通過 活躍度 欄位進行range分割槽),提高訪問速度 。
優點:無需系統層改變程式碼,活躍度改變後,會自動分割槽
2.在 使用者表中增加一個 代表活躍度的欄位,在使用者每次活躍後,其值相應增加。通過分表的方式(根據 活躍度),
缺點:需要系統層(應用程式)改變程式碼。
在使用者活躍度變化後,需要手動的從一個表變到另一個表,導致需要定期維護,較為複雜