MySQL 伺服器重載
我有一台正在苦苦掙扎的 MySQL 5.1 伺服器。我們在某些表中有太多行,並且我們沒有足夠的 RAM - 目前只有 32 GB RAM。
我的 RAM 明天開始傳遞,但我要到週日才能安裝。從那時到現在(不刪除行)我想了解是否有任何調整可以考慮稍微提高性能。
最大的問題是我們有一張包含 32+ 百萬條記錄的表。對該表的任何選擇都需要相當長的時間(如您所料)。
我的假設是機器大量使用硬碟驅動器。但我也看到 mysqld 程序的 CPU 使用率很高。
我檢查了碎片表並優化了碎片表。
該伺服器有 10 個 HDD 在 RAID 10 陣列中工作。所以 I/O 有讀寫速度的提升。
InnoDB 讀取緩衝區效率:99.98%(35291508797 次點擊/總共 35299695194) InnoDB 寫入日誌效率:81.46%(36334605 次點擊/總共 44602585 次)
任何想法或建議將不勝感激。
這是 my.cfg 文件:
[mysqld] innodb_file_per_table skip-external-locking port = 3306 socket = /var/lib/mysql/mysql.sock max_connections = 256 key_buffer_size = 256M max_allowed_packet = 100M table_open_cache = 256 sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M thread_cache_size = 8 query_cache_size = 16M max_heap_table_size = 512M tmp_table_size = 512M wait_timeout = 600 general_log_file = /var/log/mysql/mysql.general.log general_log = 0 log-slow-queries = /var/log/mysql/mysql-slow.log long_query_time = 60 # setup replication master: server-id = 1 binlog-format = mixed log-bin = /var/log/mysql/mysql-bin.log datadir = /var/lib/mysql innodb_flush_log_at_trx_commit = 1 sync_binlog = 1 # InnoDB tables innodb_flush_log_at_trx_commit = 2 innodb_additional_mem_pool_size = 256M innodb_buffer_pool_size = 20G innodb_lock_wait_timeout = 120 innodb_log_buffer_size = 32M innodb_log_file_size = 1024M [mysqld_safe] log-error = /var/log/mysqld.log pid-file = /var/run/mysqld/mysqld.pid [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash prompt =\u:>\\_ [myisamchk] key_buffer_size = 128M sort_buffer_size = 128M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout
我們有一個使用這個數據庫的應用程序。這個應用程序使用一個框架,對於頁面查詢,執行一個 count( ) 查詢來進行分頁。那些用於分頁的 count( ) 查詢是我看到的執行時間較長的查詢。
這是要求的資訊:
顯示表狀態:
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment | | intz | InnoDB | 10 | Compact | 37508536 | 562 | 21083717632 | 0 | 15220752384 | 5242880 | 42680391 | 2016-07-26 12:05:22 | NULL | NULL | latin1_swedish_ci | NULL |
…看起來我們剛剛超過 20 GB。
選擇聲明:
SELECT COUNT(*) AS count FROM intz AS INTz WHERE ((INTz.call_id_string LIKE '%3145551212%') OR (INTz.original_call_id LIKE '%3145551212%') OR (INTz.telephone_number LIKE '%3145551212%') OR (INTz.id = 3145551212) OR (INTz.ani LIKE '%3145551212%') OR (INTz.dnis LIKE '%3145551212%') OR (INTz.customer_account LIKE '%3145551212%'));
… select count(*) 大約需要 75 秒才能執行。
解釋選擇:
+----+-------------+-------------+-------+-----------------+--------------+---------+------+----------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------------+-------+-----------------+--------------+---------+------+----------+--------------------------+ | 1 | SIMPLE | intz | index | id,search_index | search_index | 313 | NULL | 40707970 | Using where; Using index | +----+-------------+-------------+-------+-----------------+--------------+---------+------+----------+--------------------------+
我在這些欄位上也有一個索引:
alter table intz add index search_index (id,call_id_string,original_call_id,telephone_number,ani,dnis,customer_account);
高 CPU 和/或 I/O - 找到最慢的查詢,提供它們,加上
EXPLAIN SELECT ...
和SHOW CREATE TABLE
. 這是最有可能解決您的問題的方法。 修復可能很簡單,例如添加“複合”索引。桌子有多大?(
SHOW TABLE STATUS
) 如果小於 20GB,額外的 RAM 可能無濟於事。對於 32GB 的 RAM,這些設置是合理的。添加更多後,請務必(僅)
innodb_buffer_pool_size
增加到大約 70% 的 RAM。
PARTITIONing
附帶 5.1。但是,它提供任何性能優勢的情況很少。在盲目開始之前,讓我們先看看查詢和模式。順便說一句,直到 5.1.43 才添加了這個構造:PARTITION BY RANGE(UNIX_TIMESTAMP(col))。 更多關於分區。附加物
OR
並LIKE
使用前導萬用字元 == 表掃描(或您的情況下的索引掃描)。索引沒有多大幫助,因為它幾乎和表格一樣大。添加一個額外的列(或者可能是一個額外的表),其中包含這些搜尋列的串聯。在上面建立一個
FULLTEXT
索引。然後用 搜尋MATCH(combined_col) AGAINST (+3145551212 IN BOOLEAN MODE)
。它將執行一千倍的速度;“成本”將消失。你會後悔購買額外的記憶體。將它用於您的查詢和計數。
但是有一些限制(字長、“字”的定義等)。