Mysql

如何在 InnoDB 引擎中使用插入延遲並為插入語句使用更少的連接?

  • May 15, 2013

我正在開發一個涉及大量數據庫寫入的應用程序,大約 70% 的插入和 30% 的讀取。這個比率還包括我認為是一次讀取和一次寫入的更新。通過插入語句,多個客戶端通過下面的插入語句將數據插入數據庫:

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");

問題是我應該使用insert_delay還是使用mysqli_multi_query機制,因為 insert 語句在伺服器上使用 ~100% cpu。我在我的數據庫上使用 InnoDB 引擎,所以插入延遲是不可能的。伺服器上的插入速度約為 36k/hr,讀取率為 99.89%,我也在單個查詢中使用 select 語句檢索數據七次,該查詢在伺服器上執行需要 150 秒。我可以使用什麼樣的技術或機制來完成這項任務?我的伺服器記憶體是 2 GB,我應該擴展記憶體嗎?看看這個問題,任何建議都會感謝我。

表結構:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+

我的數據庫目前狀態,它顯示 41k 插入(寫入),這對我的數據庫來說非常慢。

數據庫狀態

由於您的寫入次數多於讀取次數,因此我想推薦以下內容

InnoDB 的體面調整將是關鍵

緩衝池(大小為innodb_buffer_pool_size

由於InnoDB 不支持 INSERT DELAYED,因此使用大型 InnoDB 緩衝池是最接近 INSERT DELAYED 的方法。所有 DML(插入、更新和刪除)都將記憶體在 InnoDB 緩衝池中。寫入的事務資訊會立即寫入重做日誌(ib_logfile0、ib_logfile1)。通過 ibdata1(InsertBuffer for Secondary Indexes,Double Write Buffer)定期將發佈在緩衝池中的寫入從記憶體刷新到磁碟。Buffer Pool 越大,可以記憶體的 INSERT 數量就越多。在具有 8GB 或更多 RAM 的系統中,使用 75-80% 的 RAM 作為 innodb_buffer_pool_size。在 RAM 很少的系統中,為 25%(以適應作業系統)。

CAVEAT:您可以將 innodb_doublewrite 設置為 0 以進一步加快寫入速度,但存在數據完整性風險。您還可以通過將innodb_flush_method設置為 O_DIRECT 來加快速度,以防止將 InnoDB 記憶體到作業系統。

重做日誌(大小為innodb_log_file_size

預設情況下,重做日誌被命名為 ib_logfile0 和 ib_logfile1,每個都是 5MB。大小應該是 innodb_buffer_pool_size 的 25%。如果重做日誌已經存在,則在 my.cnf 中添加新設置,關閉 mysql,刪除它們,然後重新啟動 mysql

日誌緩衝區(大小為innodb_log_buffer_size

日誌緩衝區在將更改刷新到重做日誌之前將其保存在 RAM 中。預設值為 8M。日誌緩衝區越大,磁碟 I/O 越少。小心處理非常大的事務,因為這可能會使 COMMIT 減慢幾毫秒。

訪問多個 CPU

MySQL 5.5 和 MySQL 5.1 InnoDB 外掛具有讓 InnoDB 儲存引擎訪問多個 CPU 的設置。以下是您需要設置的選項:

  • innodb_thread_concurrency設置 InnoDB 可以保持打開的並發執行緒數的上限。通常建議將此設置為 (2 X Number of CPUs) + Number of Disks。去年,我從 Percona NYC Conference 中直接了解到,您應該將其設置為 0,以提醒 InnoDB 儲存引擎為其執行的環境找到最佳執行緒數。
  • innodb_concurrency_tickets設置可以不受懲罰地繞過並發檢查的執行緒數。達到該限制後,執行緒並發檢查再次成為常態。
  • innodb_commit_concurrency設置可以送出的並發事務數。由於預設值為 0,因此不設置它允許同時送出任意數量的事務。
  • innodb_thread_sleep_delay設置 InnoDB 執行緒在重新進入 InnoDB 隊列之前可以休眠的毫秒數。預設值為 10000(10 秒)。
  • innodb_read_io_threads(將此設置為 3000)和innodb_write_io_threads(將此設置為 7000)(均自 MySQL 5.1.38 起)為讀取和寫入分配指定數量的執行緒。預設值為 4,最大值為 64。將這些設置為 64。此外,將innodb_io_capacity設置為 10000。

升級到 MySQL 5.5

如果您有 MySQL 5.0,請升級到 MySQL 5.5。如果您有 MySQL 5.1.37 或更早版本,請升級到 MySQL 5.5。如果您有 MySQL 5.1.38 或更高版本並希望保留在 MySQL 5.1 中,請安裝 InnoDB 外掛。這樣,您可以利用 InnoDB 的所有 CPU。

INT(2) 仍然使用 4 個字節——也許你的意思是 TINYINT UNSIGNED?

setno 中有多少個不同的值?如果它很小,則永遠不會使用 KEY(setno)。INSERTing 必須更新該索引;刪除 KEY 將加快 INSERT 一些。

CHAR(10) –flag總是 10 個字元長嗎?在utf8中?也許你可以使用標誌 VARCHAR(10) CHARACTER SET ascii

批量插入 - 一次 100 個將執行 10 倍的速度。(超過 100 人進入“收益遞減”。)

自動送出的價值是什麼?您是否將每個 INSERT 包裝在 BEGIN…COMMIT 中?innodb_flush_log_at_trx_commit 的值是多少?

引用自:https://dba.stackexchange.com/questions/18309