手頭有一個500多萬條記錄的csv檔案,需要匯入資料庫。
一開始mysql表是預設innodb引擎的,表只有一個自增id主鍵,匯入到大概十萬左右的時候,速度緩慢到3-5條/每秒,所以這樣肯定不行。當時查閱資料之後發現myisam表會比innodb的insert速度快,所以將表改成myisam引擎,速度挺快,但是到了十五萬左右的時候速度又降下來了。
這個時候經過分析,發現瓶頸不是在insert,而是在select,我的邏輯是每次insert之前要根據orderid和productid來select查詢一下表中是否已經有資料,如果沒有再insert,瓶頸就是在select了。
到這裡的時候,我決定把orderid和productid進行md5加密之後儲存到redis中,然後之後只從redis中判斷是否已存在,如果redis中沒有的話,再去表中查詢。這個方案上了之後,insert速度又提升了,直到到了120萬條資料的時候,速度又慢下來了。
這個時候的資料都是新的,我從redis中檢索的時候總是沒有,所以還要去資料庫中去select,這個時候資料庫已經一百多萬條資料,我分析了下每次查詢都要消耗大概0.7秒,瓶頸就是在select查詢這裡,於是我決定給表添加index。
我決定給orderid和productid添加normal索引,索引有兩種類型,hash和b-tree,因為hash在你是=查詢條件的時候,可以一次定位,速度極快,因為我的select都是orderid=xxx and productid=xxx,所以決定使用hash索引。
上了索引之後,那個速度,就像飛一樣了,現在已經到了300萬了,一點沒有慢下來的意思。insert速度在每秒5000左右。
所以我後悔啊,其實根本不需要額外使用redis來儲存索引,mysql表自己的索引就很快。當然我在redis中儲存索引是因為我的指令碼總是掛,每次都要重新開始檢索檔案,所以也還有一定作用。
當然最後我才發現,csv檔案可以直接匯入mysql的。。。。。。瞬間感覺自己秀逗了。。。。。。
但是還好吧,如果不這麼繞一圈,我也不會發現這麼多問題,學到一些東西吧。
總結:
以後涉及到資料表的操作的,首先要考慮索引,另外如果要操作的資料量比較大,可以採用分庫分表來操作,可以酌情分為20-100等等個表來倡導做。當然目前來看一個表資料到了幾百萬速度都沒有多慢,所以如果要分庫分表的話,估計是個天文數字才會用到。