2010-09-12 40 views
28

發生了什麼事情的簡短回顧。我正在處理7100萬條記錄(與其他人處理的數十億條記錄相比,數量並不多)。在另一個thread上,有人建議我的羣集的當前設置不適合我的需要。我的表結構是:帶有8000萬條記錄並添加索引的表需要超過18小時(或永遠)!怎麼辦?

CREATE TABLE `IPAddresses` (
    `id` int(11) unsigned NOT NULL auto_increment, 
    `ipaddress` bigint(20) unsigned default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM; 

我加71萬條記錄,然後做了一個:

ALTER TABLE IPAddresses ADD INDEX(ipaddress); 

它已經14小時,該操作仍然沒有完成。在谷歌搜索,我發現有一個衆所周知的方法來解決這個問題 - 分區。我知道我需要現在基於ipaddress分區我的表,但是我可以在不重新創建整個表的情況下執行此操作嗎?我的意思是,通過一個ALTER語句?如果是的話,有一個要求說要分區的列應該是主鍵。我將使用這個ipaddress的id來構造一個不同的表,所以ipaddress不是我的主鍵。在給定此場景的情況下,如何分區我的表格?

+1

MySQL自己的分區文檔:http://dev.mysql.com/doc/refman/5.1/en/partitioning.html – 2010-09-12 19:06:46

+1

id字段完全是不必要的。 – 2010-09-12 22:04:43

+0

@Seun:在這種情況下,如果我想要構建一個包含say,URI | ipaddress的表,並且想要使用與ip地址關聯的id,我將如何做到這一點?我試圖規範一個不同的表格,首先要求創建這張表格。有什麼建議麼? – Legend 2010-09-12 22:09:10

回答

34

好原來,這個問題不僅僅是一個簡單的多創建一個表,索引和忘記的問題:)這是我做以防萬一別人面臨着同樣的問題(我用的IP地址的一個例子,但它適用於其他數據類型太):

問題:你的表有百萬條目,你需要添加一個索引非常快

USECASE:考慮將數以百萬計的IP地址的查找表。添加IP地址不應該是一個大問題,但在它們上創建索引需要超過14個小時。

解決方案:分區使用MySQL's Partitionin克策略表格

案例#1:當你想表尚未創建

CREATE TABLE IPADDRESSES(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    ipaddress BIGINT UNSIGNED, 
    PRIMARY KEY(id, ipaddress) 
) ENGINE=MYISAM 
PARTITION BY HASH(ipaddress) 
PARTITIONS 20; 

案例#2:當表你想要已經創建。 似乎有一種方法,使用ALTER TABLE來做到這一點,但我還沒有想出這個妥善的解決辦法。相反,有一個效率稍低的解決方案:

CREATE TABLE IPADDRESSES_TEMP(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    ipaddress BIGINT UNSIGNED, 
    PRIMARY KEY(id) 
) ENGINE=MYISAM; 

將您的IP地址插入到此表中。然後創建實際的表分區:

CREATE TABLE IPADDRESSES(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    ipaddress BIGINT UNSIGNED, 
    PRIMARY KEY(id, ipaddress) 
) ENGINE=MYISAM 
PARTITION BY HASH(ipaddress) 
PARTITIONS 20; 

然後終於

INSERT INTO IPADDRESSES(ipaddress) SELECT ipaddress FROM IPADDRESSES_TEMP; 
DROP TABLE IPADDRESSES_TEMP; 
ALTER TABLE IPADDRESSES ADD INDEX(ipaddress) 

和你去那裏......對新表的索引我花了大約2個小時3.2GHz的機器上,擁有1GB RAM :)希望這有助於。

3

您正在使用的被近期內取消的MyISAM。另一種選擇是InnoDB。

「的InnoDB是MySQL事務安全(ACID兼容)存儲引擎,具有提交,回滾和崩潰恢復功能來保護用戶數據。InnoDB行級鎖定(無需升級到更粗粒度鎖)和Oracle樣式一致的非鎖定讀取可提高多用戶併發性和性能。 InnoDB將用戶數據存儲在聚簇索引中,以減少基於主鍵的常見查詢的I/O。爲了保持數據的完整性,InnoDB還支持FOREIGN KEY引用完整性約束。你可以自由地與其他MySQL存儲引擎的表混合InnoDB表,甚至在同一個聲明「\

http://dev.mysql.com/doc/refman/5.0/en/innodb.html

據:

http://dev.mysql.com/tech-resources/articles/storage-engine/part_1.html

,你應該能夠切換在不同的引擎之間通過使用一個簡單的改變命令可以讓你有一定的靈活性,同時也說明你的數據庫中的每個表格都可以獨立配置

+0

感謝您的指點。不過,我目前正在尋找一個MyISAM特定的解決方案,但我將隨後準備一個轉移到InnoDB的計劃。 – Legend 2010-09-16 20:42:00

7

Creati MySQL的索引很慢,但並不慢。擁有7100萬條記錄,應該需要幾分鐘,而不是14個小時。可能出現的問題有:

  • 您還沒有配置排序緩衝區大小和其他配置選項

這裏看看:http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_myisam_sort_buffer_size

如果您嘗試生成具有8MB 1GB的索引排序緩存它會取得很多通行證。但是如果緩衝區大於CPU緩存,它會變慢。所以你必須測試一下,看看哪些效果最好。

  • 有人在桌子上的鎖
  • 您的IO系統很爛
  • 您的服務器交換

像往常一樣檢查的iostat,vmstat的,日誌等發出一個鎖定桌子上的鎖定表,以檢查是否有人鎖定它。

FYI我的64位桌面上創建10M隨機BIGINTs指數上需要17S ...

0

在表格中。你已經插入了710億條記錄。現在,如果要在表的主鍵列上創建分區,可以使用alter table選項。給出一個例子供您參考。

CREATE TABLE t1 (
    id INT, 
    year_col INT 
); 

ALTER TABLE t1 
    PARTITION BY HASH(id) 
    PARTITIONS 8; 
5

我遇到了問題,我想通過添加索引來加快查詢速度。該表只有大約300.000條記錄,但它也花了太長時間。當我檢查了mysql服務器進程時,事實證明,我試圖優化的查詢仍在後臺運行。 4次!在我殺死了這些查詢之後,編制索引的工作很快就完成了。也許同樣的問題適用於你的情況。

+1

顯示進程列表; kill [query | connection] {process_id}; – BuzzCloudAU 2015-06-26 22:06:24

相關問題