突然不得不重建索引以防止网站宕机

bra*_*ley 7 mysql

我一直有这个问题一段时间:https : //stackoverflow.com/questions/7770695/mysql-query-slow-until-reindex-column

看起来一切都很好,当我突然对表进行大量写入时,索引似乎死了,查询最多需要 2 秒。当我有很多流量时总是会发生这种情况,因此连锁反应几乎会使我的数据库服务器停机。

如果我重建索引,一切都会好起来的。什么可能导致索引中的这些突然“中断”?如何预防?

表定义:

+---------------+-----------------------+------+-----+---------+----------------+
| Field         | Type                  | Null | Key | Default | Extra          |
+---------------+-----------------------+------+-----+---------+----------------+
| id            | int(11) unsigned      | NO   | PRI | NULL    | auto_increment |
| user_id       | mediumint(8) unsigned | YES  | MUL | NULL    |                |
| created       | int(11) unsigned      | YES  | MUL | NULL    |                |
| track         | int(11) unsigned      | YES  | MUL | NULL    |                |
| prop          | int(11) unsigned      | YES  | MUL | NULL    |                |
| sequence      | text                  | YES  |     | NULL    |                |
| location      | varchar(255)          | YES  |     | NULL    |                |
| type          | tinyint(1) unsigned   | YES  | MUL | NULL    |                |
| flagged       | int(11) unsigned      | YES  | MUL | 0       |                |
| status        | tinyint(1) unsigned   | YES  | MUL | 0       |                |
| featured      | tinyint(1) unsigned   | YES  | MUL | 0       |                |
| recommended   | tinyint(1) unsigned   | YES  |     | 0       |                |
| rendered      | tinyint(1) unsigned   | YES  |     | NULL    |                |
| fms_id        | varchar(32)           | YES  | MUL | NULL    |                |
| comments      | text                  | YES  |     | NULL    |                |
| tv            | tinyint(1) unsigned   | YES  |     | 0       |                |
| performers    | varchar(255)          | YES  |     | NULL    |                |
| comp_34_votes | int(11) unsigned      | YES  |     | 0       |                |
| comp_35_votes | int(11)               | YES  |     | 0       |                |
| comp_36_votes | int(11)               | YES  |     | 0       |                |
+---------------+-----------------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

和突然变慢的查询(如果我删除 orderby 它并不慢):

SELECT sql_no_cache `p`.`id` as performance_id, `p`.`performers`, `t`.`name` as track_name, `p`.`location`, `p`.`fms_id`
FROM (`performances` p)
JOIN `tracks` t ON `p`.`track` = `t`.`id`
WHERE (p.status = 1 OR (p.status != 2 && p.flagged < 3))
AND `p`.`prop` IN ('1', '2', '3', '4', '5', '6', '8', '10', '11', '13') 
AND `p`.`track` IN ('17', '9', '5', '15', '2', '3', '8', '6', '12', '4', '1') 
AND `p`.`type` IN ('1', '0', '2') 
ORDER BY `p`.`created` desc
LIMIT 11, 12
Run Code Online (Sandbox Code Playgroud)

和解释:

+----+-------------+-------+--------+--------------------------------+--------------+---------+--------------------------------+------+-------------+
| id | select_type | table | type   | possible_keys                  | key          | key_len | ref                            | rows | Extra       |
+----+-------------+-------+--------+--------------------------------+--------------+---------+--------------------------------+------+-------------+
|  1 | SIMPLE      | p     | index  | track,prop,flagged,status,type | created_desc | 5       | NULL                           |   45 | Using where |
|  1 | SIMPLE      | t     | eq_ref | PRIMARY                        | PRIMARY      | 4       | db_123.p.track |    1 | Using where |
+----+-------------+-------+--------+--------------------------------+--------------+---------+--------------------------------+------+-------------+
Run Code Online (Sandbox Code Playgroud)

Rol*_*DBA 4

问题并不是真正的索引碎片。它与索引统计数据相关性更大。如果您使用 MyISAM,INSERT 的突然峰值会使 MySQL 查询优化器无法识别统计信息。这将导致 MySQL 查询优化器在 SELECT 查询的 EXPLAIN 计划中进行可怕的猜测。

如果你使用InnoDB,ANALYZE TABLE就变得完全没用了。

只要表相当小,ANALYZE TABLE您就可以为 MyISAM 做所有的事情了。定期重建索引可能会对 InnoDB 表有所帮助。

只要表不被大量写入,索引统计信息就会保持稳定,并且查询 EXPLAIN 计划将保持更加一致。

请记住:一旦您拥有大量INSERTsUPDATEs、 和DELETEs,那么在下一次重建或 之前,所有值得信赖的索引统计数据的赌注都会被取消ANALYZE TABLE