如何提高mysql導入表數據的速度

轉自http://hi.baidu.com/0x14/blog/item/6a6a8aff7240bb3a5d600875.html


通過使用

----begin----

set autocommit = 0; 

...

commit;

----end----

能非常明顯地看到變化,飛躍了。


1、如果mysql的data數據很少,內存足夠大,可以把data防止到內存盤中。

linux如下設置內存盤:

mount -t ramfs none /ram

默認使用內存一半

如果內存不夠大,系統有多個硬盤,則把mysql應用程序和data目錄分開到不同硬盤上。

2、mysql的表設置爲myiasm,比同等條件下的innodb能快20倍以上

3、導入完成以後才創建數據庫索引

4、導入完成以後根據需要轉換爲其他engine,比如innodb

5、多條數據插入一個表,可以使用多記錄方式:

insert into tablename values('xxx','xxx'),('yyy','yyy')...;

6、如果多個mysql執行導入,可以使用delayed

insert delayed into tablename values('sss','ssss');

7、大文件sql文件可以用split分成多份再導

8、同等條件下,redhat比ubuntu強很多(幾乎肯定)

9 性能調整技巧(Performance tuning tips)

1. 如果 Unix top 或 Windows 任務管理器(Task Manager) 顯示服務的 CPU 佔用率小於 70%,(shows that the CPU usage percentage with your workload is less than 70 %,)你的系統瓶頸可能在磁盤讀寫上。或許你提交了大量的事務,或者是緩衝池(buffer pool)太小了。將緩衝池設大點會有所幫助,但一定要注意不能大於物理內存的 80%。

2. 在一個事務中包含幾個修改。如果事務對數據庫進行了修改,那麼在這個事務提交時 InnoDB 必須刷新日誌到磁盤上。因爲硬盤的旋轉速度通常至多爲 167 轉/秒,那麼只要磁盤不欺騙操作系統,提交的事務數目限止也同樣爲 167 次/秒·用戶。

3. 如果掉失最近的幾個事務無所謂的話,可以在 my.cnf 文件中將參數 innodb_flush_log_at_trx_commit 設置爲 0。InnoDB 無論如何總是嘗試一秒刷新(flush)一次日誌,儘管刷新並不能得到保證。

4. 將日誌文件(log files)設大一點,使日誌文件的總和正好與緩衝池(buffer pool)一樣大。當 InnoDB 用光日誌文件的空間時,它不得不在一個時間點上將緩衝池內修改過的內容寫到磁盤上。 小的日誌文件可能引起不必要的磁盤寫操作。但是大的日誌文件的缺點就是在數據恢復時將佔用較長的時間。

5. 同樣 log buffer 儘量設大點,比如說 8 MB。
6. 如果要存儲變長的字符串或字段可能會包含大量的 NULLs,請使用 VARCHAR 型字段代替 CHAR 。一個 CHAR(n) 字段總是使用 n bytes 來存儲數據,即使這個字符串很短或是一個 NULL 值。較小的表更加適合緩衝池同時能夠減少磁盤 I/O 。

7. (適合從 3.23.41 以上版本) 在某些版本的 Linux 和 Unixes 中,使用 Unix fsync 或其它類似的方法將文件刷新到磁盤是異常地慢的。InnoDB 默認的方法就是 fsync 。如果你對數據庫系統的磁盤寫性能不能感到滿意,你可以嘗試在 my.cnf 中將 innodb_flush_method 設置爲 O_DSYNC,儘管 O_DSYNC 選項在多數的系統上看起來比較慢。

8. 在向 InnoDB 導入數據時,請確認 MySQL 沒有打開 autocommit=1 。否則每個插入語句都要將 log 刷新到磁盤。在你的 SQL 導入文件的第一行加入

set autocommit=0;

並在最後一行加入

commit;
 

如果使用 mysqldump 選項 --opt,你將會得到一個快速導入 InnoDB 表的轉儲(dump)文件,甚至可以不再使用上面所提的 set autocommit=0; ... commit; 。

9. 小心 insert 集全的大回滾(roolback):在插入時 InnoDB 使用插入緩衝來減少磁盤 I/O,但在相應的回滾中卻沒有使用這樣的機制。一個 disk-bound rollback 可能會花費相應插入時間的 30 倍。如果發生一個失控的回滾,你可以查看第 6.1 章節的技巧來停止它。

10. 同樣也要小心一個大的 disk-bound 的操作。使用 Drop TABLE 或 TRUNCATE (從 MySQL-4.0 以上) 來清空一個表,而不要使用 Delete FROM yourtable。

11. 如果需要插入大量記錄行可以使用多行(multi-line)的 Insert 來減少客戶端與服務器端的通信開銷:

Insert INTO yourtable VALUES (1, 2), (5, 5);

這個技巧對插入任何表均有效,而不僅僅是 InnoDB。

12. 如果在輔鍵上有 UNIQUE 約束,從 3.23.52 和 4.0.3 開始,可以通過在一個導入會話中將唯一鍵檢查(uniqueness check)關閉來提高數據導入速度:

SET UNIQUE_CHECKS=0;

一個大的表導入這將減少大量的磁盤 I/O,因爲這時 InnoDB 可能使用自身的插入緩衝來分批地記錄輔助索引。

 

13. 如果在表中有一個子 FOREIGN KEY 約束,從 3.23.52 和 4.0.3 開始,可以通過在一個導入會話中將外鍵檢查(foreign key check)關閉來提高數據導入速度:

SET FOREIGN_KEY_CHECKS=0;

對一個大的表導入這將減少大量的磁盤 I/O。

9.1 InnoDB 監視器(Monitors)

從版本 3.23.42 開始,InnoDB 中就包含了 InnoDB Monitors,它可以顯示出 InnoDB 的內部狀態。從版本 3.23.52 和 4.0.3 開始,你可以使用一個新的 SQL 命令

SHOW INNODB STATUS

來讀取標準 InnoDB Monitor 給 SQL client 的輸出信息。這些信息對性能調整有益。

 

另外一個使用 InnoDB Monitors 方法就是讓它在服務程序 mysqld 的標準輸出上持續地寫出信息。當開關打開時,InnoDB Monitors 大約每 15 秒顯示一次數據(注意:MySQL 的客戶端並不會顯示任何東西)。一個簡單地使用它的方法就是以一個命令行方式執行 mysqld 。否則輸出將會定向到 MySQL 服務錯誤日誌(error log file)中 'yourhostname'.err (在 Windows 下爲 mysql.err),在 Windows 系統中必須在 MS-DOS 使用提示符下以 --console 選項運行 mysqld-max 來指令信息輸出在命令提示符窗口上。

顯示的信息包含下列信息:

* 每一個活動的事務(active transaction)保持的表和記錄鎖定
* 事務的鎖等待 (lock waits of a transactions)
* 線程的信號量等待 (semaphore waits of threads)
* 文件 I/O 的等待請求 (pending file i/o requests)
* 緩衝池(buffer pool)的統計信息
* InnoDB 主線程的 purge buffer 和 insert buffer 歸併活動(merge activity)

 

通過下列的 SQL 命令,可以使標準的 InnoDB Monitor 記錄到標準的 mysqld 的輸出上:

Create TABLE innodb_monitor(a int) type = innodb;

通過它來停止:

Drop TABLE innodb_monitor;

Create TABLE 句法只不過是爲了通過 MySQL SQL 語法分析而提供給 InnoDB 引擎命令的一種方式:那個被創建的表根本與 InnoDB Monitor 無任何關係。如果你在監視器運行着的狀態下關閉數據庫,並且你需要再次啓動監視器, 那麼你不得不在發出一個新的 Create TABLE 來啓動監視器之前先移除(drop)這個表。

 

與之相類似的,你可以啓動 innodb_lock_monitor ,它在某些方面與 innodb_monitor 一致,但是它會顯示更多的鎖定信息。一個單獨的 innodb_tablespace_monitor 將顯示在現有表空間內所建立的文件段列表以及可以分配數據結構的有效表空間。從 3.23.44 開始,提供了 innodb_table_monitor ,通過它可以獲得 InnoDB 內部數據字典的信息。

3.23.52 中 InnoDB 輸出的示例:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章