MySQL兩千萬資料優化&遷移
最近有一張2000W條記錄的資料表需要優化和遷移。2000W資料對於MySQL來說很尷尬,因為合理的建立索引速度還是挺快的,再怎麼優化速度也得不到多大提升。不過這些資料有大量的冗餘欄位和錯誤資訊,極不方便做統計和分析。所以我需要建立一張新表,把舊錶中的資料一條一條取出來優化後放回新表;
一. 清除冗餘資料,優化欄位結構
2000W資料中,能作為查詢條件的欄位我們是預知的。所以將這部分資料單獨建立新的欄位,對於有規則的資料合理改變欄位結構,比如身份證就是varchar(18)。對於不重要的資料我們合併後存在一個結構為text的欄位。
對於一些有關聯的資料我們需要計算,常見的比如身份證種能獲取到準確的性別,出生地、生日、年齡。
二. 資料遷移
我們從資料庫中取出一條舊資料,再通過計算處理後得到想要的新資料,最後將新資料插入新表。不過在獲取新資料時遇到如下問題。
-
資料量太大,無法一次獲取(2000W資料扔到記憶體挺可怕的);
我們可以通過MySQL的limit語法分批獲取。比如每次獲取50000,SQL語句如下:
select * from table_name limit 15000000,50000;
通過這種方法能解決資料量太大的問題,但是隨著limit的第一個引數越來越大,查詢速度會慢的嚇人(上面這條SQL執行會花35秒)。時間就是生命,於是我們開始優化SQL語句,優化後變成下面這樣:
select * from table_name order by id desc limit 5000000,50000;
可通過二分法拆分2000W資料,當執行到1000W資料時,將資料倒序。優化後SQL執行效率顯著提升,從35秒降到9秒;
不過還是很慢,時間就是生命……還好我們有自增ID(建立資料表第一條定律,一定要有自增欄位),優化後的SQl如下:
1. select * from table_name where id>15000000 and id<15050000; 2. select * from table_name where id>15000000 limit 50000;
為了直觀演示,我寫了兩條功能一樣的SQL。相比第一條,第二條的limit會導致SQL的索引命中變差,效率同樣也會下降。第一條SQL的執行時間是2毫秒,第二條執行時間5毫秒(我取的平均值)。每次資料的查詢速度直接從35秒降到2毫秒……
-
資料量太大並且資料無法預估,某些特殊資料會導致資料匯入失敗;
我們有三種方案去將新資料存入新表,分別如下:
- 一條一條插入資料;
開始肯定會想這種方案一定不行,因為每次插入都會有一次資料庫IO操作。但是該方案有個好處是能及時發現有問題的資料,修改後再繼續執行; 在Oracle中使用『繫結變數』能帶來效能提升,正好MySQL也提供了『繫結變數』的功能。於是在不改變邏輯的情況下,嘗試優化資料儲存速度。程式碼如下:
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(); }
最後效果不怎麼好,MySQL的『繫結變數』並沒帶來明顯的速度提升,不過能有效的防止SQL隱碼攻擊;
- 一次插入50000條資料;
這是我最後選中的方案,一是能及時發現有問題的資料,二是匯入資料非常穩定。就像支援斷點續傳一樣,每一步都能看到效果。在執行指令碼時,也能同步開始寫分析邏輯;
- 組裝成SQL檔案,最後統一匯入;
組裝一個大的SQL檔案,最後通過MySQL自帶的工具匯入也是極好的。但如果有一條SQL有問題,你可能需要重跑一次指令碼。因為在9G大小的文字檔案中修改一個符號是很痛苦的事情……
三. 總結
通過各種優化,最後將指令碼執行時間縮短到了20分鐘內。優化後資料質量得到了較高保證,下次將嘗試2億資料的優化&遷移……
PS:原文地址 http://blog.it2048.cn/article_2000w-data.html 之後我會陸續把自己部落格遷移到雲棲社群,希望大家關注!
相關文章
- Mysql資料遷移方法MySql
- 遷移MySQL 5.7資料庫MySql資料庫
- MySQL 資料遷移Oracle工作MySqlOracle
- mysql資料庫遷移 mysqldumpMySql資料庫
- 提高mysql千萬級大資料SQL查詢優化30條經驗(Mysql索引優化注意)MySql大資料優化索引
- 一個跨平臺資料遷移的方案優化優化
- MySQL資料遷移那些事兒MySql
- linux mysql資料庫遷移LinuxMySql資料庫
- Django資料從sqlite遷移資料到MySQLDjangoSQLiteMySql
- MySQL資料庫遷移與MySQL資料庫批量恢復MySql資料庫
- Mysql百萬級資料遷移,怎麼遷移?實戰過沒?MySql
- MySql資料庫遷移圖文展示MySql資料庫
- MySQL 千萬資料庫深分頁查詢優化,拒絕線上故障!MySql資料庫優化
- 資料從Oracle向Mysql資料遷移例項OracleMySql
- 遷移資料.
- mysql千萬級資料量根據索引優化查詢速度MySql索引優化
- mysql 備份與遷移 資料同步方法MySql
- sqlldr 完成mysql到oracle的資料遷移MySqlOracle
- 【遷移】使用rman遷移資料庫資料庫
- MySQL的count(*)的優化,獲取千萬級資料表的總行數MySql優化
- 效能優化之資料庫篇5-分庫分表與資料遷移優化資料庫
- 線上資料遷移,數字化時代的必修課 —— 京東雲資料遷移實踐
- MySQL資料庫優化MySql資料庫優化
- 【資料遷移】使用傳輸表空間遷移資料
- 1.0 ORACLE到MYSQL資料遷移方式選型OracleMySql
- Centos MySQL資料庫遷移詳細步驟CentOSMySql資料庫
- Mysql百萬級資料遷移實戰筆記MySql筆記
- 從MySQL到Redis提升資料遷移的效率MySqlRedis
- 一個簡單的MySQL資料遷移示例MySql
- Kafka資料遷移Kafka
- 資料庫遷移資料庫
- redis資料遷移Redis
- 轉資料遷移
- ORACLE 資料遷移Oracle
- DXWB 資料遷移
- 資料的遷移
- Harbor資料遷移
- Oracle資料的優化器有兩種優化方法:Oracle優化