最近有一張2000W條記錄的數據表須要優化和遷移。2000W數據對於MySQL來講很尷尬,由於合理的建立索引速度仍是挺快的,再怎麼優化速度也得不到多大提高。不過這些數據有大量的冗餘字段和錯誤信息,極不方便作統計和分析。因此我須要建立一張新表,把舊錶中的數據一條一條取出來優化後放回新表;html
一. 清除冗餘數據,優化字段結構mysql
2000W數據中,能做爲查詢條件的字段咱們是預知的。因此將這部分數據單首創建新的字段,對於有規則的數據合理改變字段結構,好比身份證就是varchar(18)。對於不重要的數據咱們合併後存在一個結構爲text的字段。sql
對於一些有關聯的數據咱們須要計算,常見的好比身份證種能獲取到準確的性別,出生地、生日、年齡。數據庫
二. 數據遷移ide
咱們從數據庫中取出一條舊數據,再經過計算處理後獲得想要的新數據,最後將新數據插入新表。不過在獲取新數據時遇到以下問題。工具
1. 數據量太大,沒法一次獲取(2000W數據扔到內存挺可怕的);性能
咱們能夠經過MySQL的limit語法分批獲取。好比每次獲取50000,SQL語句以下:優化
SQLspa
select * from table_name limit 15000000,50000;
SQLcode
Copy
經過這種方法能解決數據量太大的問題,可是隨着limit的第一個參數愈來愈大,查詢速度會慢的嚇人(上面這條SQL執行會花35秒)。時間就是生命,因而咱們開始優化SQL語句,優化後變成下面這樣:
SQL
select * from table_name order by id desc limit 5000000,50000;
SQL
Copy
可經過二分法拆分2000W數據,當執行到1000W數據時,將數據倒序。優化後SQL執行效率顯著提高,從35秒降到9秒;
不過仍是很慢,時間就是生命……還好咱們有自增ID(建立數據表第一條定律,必定要有自增字段),優化後的SQl以下:
SQL
1. select * from table_name where id>15000000 and id<15050000; 2. select * from table_name where id>15000000 limit 50000;
SQL
Copy
爲了直觀演示,我寫了兩條功能同樣的SQL。相比第一條,第二條的limit會致使SQL的索引命中變差,效率一樣也會降低。第一條SQL的執行時間是2毫秒,第二條執行時間5毫秒(我取的平均值)。每次數據的查詢速度直接從35秒降到2毫秒……
2. 數據量太大而且數據沒法預估,某些特殊數據會致使數據導入失敗;
咱們有三種方案去將新數據存入新表,分別以下:
1. 一條一條插入數據;
開始確定會想這種方案必定不行,由於每次插入都會有一次數據庫IO操做。可是該方案有個好處是能及時發現有問題的數據,修改後再繼續執行; 在Oracle中使用『綁定變量』能帶來性能提高,正好MySQL也提供了『綁定變量』的功能。因而在不改變邏輯的狀況下,嘗試優化數據存儲速度。代碼以下:
PHP
public function actionTest(array $data) { $mysqli = new mysqli("192.168.1.106", "username", "password", "test"); $sql = "insert into table_name(name,identity) values (?,?)"; $stmt = $connection->prepare($sql); $name = ""; $identity = ""; //使用綁定變量 $stmt->bind_param("si", $name, $identity); foreach($data as $val) { $name = $val[name]; $identity = $val[card_id]; //執行 $stmt->execute(); } $stmt->close(); }
PHP
Copy
最後效果不怎麼好,MySQL的『綁定變量』並沒帶來明顯的速度提高,不過能有效的防止SQL注入;
2. 一次插入50000條數據;
這是我最後選中的方案,一是能及時發現有問題的數據,二是導入數據很是穩定。就像支持斷點續傳同樣,每一步都能看到效果。在執行腳本時,也能同步開始寫分析邏輯;
3. 組裝成SQL文件,最後統一導入;
組裝一個大的SQL文件,最後經過MySQL自帶的工具導入也是極好的。但若是有一條SQL有問題,你可能須要重跑一次腳本。由於在9G大小的文本文件中修改一個符號是很痛苦的事情……
三. 總結
經過各類優化,最後將腳本執行時間縮短到了20分鐘內。優化後數據質量獲得了較高保證,下次將嘗試2億數據的優化&遷移……
做者: 極客導航(http://it2048.cn/)極客博客(http://blog.it2048.cn/) 文章地址: http://blog.it2048.cn/article_2000w-data.html