2010-03-20 303 views
32

任何人都可以告訴我如何在MySQL中添加一個關鍵的縮放比例嗎?我在數據庫中有500,000,000行trans,列i(INT UNSIGNED),j(INT UNSIGNED),nu(DOUBLE),A(DOUBLE)。 我嘗試索引一列,例如MySQL - 創建索引需要多長時間?

ALTER TABLE trans ADD KEY idx_A (A); 

我等。對於一張14,000,000行的表格,在我的MacBook Pro上執行大約需要2分鐘,但是在整個五十億的時間內,它需要花費15個小時並計數。我做錯了什麼,還是我只是天真的關於如何索引數據庫與行數的比例?

+0

你可能想看看分裂(數據庫分片)你的表 – 2010-03-20 14:02:03

回答

27

有幾個因素要考慮:

  • 排序是一個N.log(N)的操作。
  • 14M行的排序可能適合主內存; 500M行的排序可能不會,所以排序會溢出到磁盤上,這會極大地降低速度。

由於該因子大小約爲30,所以大數據集的名義排序時間將是50小時的數量級 - 在兩小時以內。但是,每個數據值需要8個字節,而另外需要8個字節的開銷(如果你更瞭解它在索引中存儲的內容,那麼這是對mySQL的猜測)。所以,14M×16≈220 MB的主內存。但是500M×16≈8GB的主內存。除非你的機器有足夠的內存空間(並且配置了MySQL),否則大部分內容都會溢出到磁盤上,並且在剩下的時間裏佔了很大一部分。

+1

非常感謝,這對我有意義 - 我只有4 GB。看起來像上面提到的那樣分割(分割?)數據很有意義。 – xnx 2010-03-21 22:20:44

+0

你把你的桌子拆了嗎?它花了多少時間? – juanpastas 2014-03-10 00:14:58

2

從我的經驗來看:如果硬件能夠應付它,用MySQL索引大型表格通常會非常線性地縮放。到目前爲止,我已經嘗試了大約100,000,000行的表格,但不是在筆記本上 - 主要是在強大的服務器上。我猜它主要取決於硬件因素,你使用的表引擎的類型(MyIsam,INNO,或其他),以及如果表格之間在其他地方使用的話,有點有點不同。當我這樣做時,與CPU使用率不同,通常磁盤使用率跳高。不確定MacBook的硬盤,但我想他們不是最快的。

如果您擁有MyISAM表格,也許可以仔細查看錶格目錄中的索引文件,並查看它隨時間變化的情況。

+0

感謝您的快速回復,Björn。我遵循你的建議。我把它的文件 #SQL-a8_6.MYD(目前7455506432字節)和 #SQL-a8_6.MYI(目前2148865024字節) 是數據庫和新版本正在建造我分別要求的指標? 然後,如果原始表格是 trans.MYD(12,645,156,375字節) 我約完成了60%? 現在看起來我會更好地將巨大的桌子分成20個或更小的桌子。 謝謝, 基督徒 – xnx 2010-03-20 14:47:14

+0

總的來說應該是這樣。那麼,這一切都取決於你想要處理的數據量。 500.000.000行很多,所以如果你想在之後做一些奇妙的報告,儘量減少數據。試圖分裂它,或者在MySQLs分區功能(從版本5.1)中獲取戰利品。 – Bjoern 2010-03-20 19:14:40

5

首先,您的表格定義可能會在這裏產生很大的不同。如果您的列中不需要NULL值,請將其定義爲NOT NULL。這將節省索引中的空間,並且在創建索引時大概需要時間。

CREATE TABLE x ( 
    i INTEGER UNSIGNED NOT NULL, 
    j INTEGER UNSIGNED NOT NULL, 
    nu DOUBLE NOT NULL, 
    A DOUBLE NOT NULL 
); 

至於創建索引所花費的時間,這需要一個表掃描,並會顯示爲REPAIR BY SORTING。在你的情況下(即海量數據集)應該更快地創建一個具有所需索引的新表並將數據插入到該表中,因爲這樣可以避免操作,因爲索引是按順序在插入上構建的。在this article中有一個類似的概念。

CREATE DATABASE trans_clone; 
CREATE TABLE trans_clone.trans LIKE originalDB.trans; 
ALTER TABLE trans_clone.trans ADD KEY idx_A (A); 

然後腳本插入到數據塊(根據文章),或使用MYSQLDUMP轉儲數據:

mysqldump originalDB trans --extended-insert --skip-add-drop-table --no-create-db --no-create-info > originalDB .trans.sql 
mysql trans_clone < originalDB .trans.sql 

這將插入的數據,但不會需要一個索引重建(索引隨着每行插入而建立)並且應該更快地完成。

+1

請注意,您可以使用[pt-online-schema-change](http://www.percona),而不是執行一個'mysqldump'和一個恢復過程,這個恢復過程至少需要連續的表讀鎖從Percona工具包 - 它會照顧創建和複製數據在多個過程中,刪除連續鎖定要求。 – 2014-08-21 23:37:56

0

所以theorically如果排序步驟是N.log(N)操作,partitionning你的大表將節省時間操作

約30%的漲幅爲100個等於文件partitionned 500個000 000行的表:因爲 500 000 000 *日誌(500 000 000)= 4 349 485 002 和 100 *(500 000 000/100 * LOG(500 000 000/100))= 3 349 485 002