+----------------------------+------------------------------------------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+------------------------------------------------------------------------------+------+-----+---------+----------------+
| type | enum('Website','Facebook','Twitter','Linkedin','Youtube','SeatGeek','Yahoo') | NO | MUL | NULL | |
| name | varchar(100) | YES | MUL | NULL | |
| processing_interface_id | bigint(20) | YES | MUL | NULL | |
| processing_interface_table | varchar(100) | YES | MUL | NULL | |
| create_time | datetime | YES | MUL | NULL | |
| run_time | datetime | YES | MUL | NULL | |
| completed_time | datetime | YES | MUL | NULL | |
| reserved | int(10) | YES | MUL | NULL | |
| params | text | YES | | NULL | |
| params_md5 | varchar(100) | YES | MUL | NULL | |
| priority | int(10) | YES | MUL | NULL | |
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| status | varchar(40) | NO | MUL | none | |
+----------------------------+------------------------------------------------------------------------------+------+-----+---------+----------------+
select * from remote_request use index ( processing_order ) where remote_request.status = 'none' and type = 'Facebook' and reserved = '0' order by priority desc limit 0, 40;
此表接收极大量的写入和读取。每个remote_request最终都是一个进程,它可以在0到5个其他remote_requests之间产生任何地方,具体取决于请求的类型和请求的作用。
该表目前约有350万条记录,当网站本身处于高负荷状态时,它会进入蜗牛节目,并且我有超过50个或更多的实例同时运行。 (如果你不确定的话,REST请求就是表的目的。)
随着桌子的增长,它变得越来越糟。我可以每天清除处理过的请求,但最终这并不能解决问题。
我需要的是此查询始终具有非常低的响应率。
以下是表格中的当前索引。
+----------------+------------+----------------------------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------+------------+----------------------------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| remote_request | 0 | PRIMARY | 1 | id | A | 2403351 | NULL | NULL | | BTREE | | |
| remote_request | 1 | type_index | 1 | type | A | 18 | NULL | NULL | | BTREE | | |
| remote_request | 1 | processing_interface_id_index | 1 | processing_interface_id | A | 18 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | processing_interface_table_index | 1 | processing_interface_table | A | 18 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | create_time_index | 1 | create_time | A | 160223 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | run_time_index | 1 | run_time | A | 343335 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | completed_time_index | 1 | completed_time | A | 267039 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | reserved_index | 1 | reserved | A | 18 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | params_md5_index | 1 | params_md5 | A | 2403351 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | priority_index | 1 | priority | A | 716 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | status_index | 1 | status | A | 18 | NULL | NULL | | BTREE | | |
| remote_request | 1 | name_index | 1 | name | A | 18 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | processing_order | 1 | priority | A | 200 | NULL | NULL | YES | BTREE | | |
| remote_request | 1 | processing_order | 2 | status | A | 200 | NULL | NULL | | BTREE | | |
| remote_request | 1 | processing_order | 3 | type | A | 200 | NULL | NULL | | BTREE | | |
| remote_request | 1 | processing_order | 4 | reserved | A | 200 | NULL | NULL | YES | BTREE | | |
+----------------+------------+----------------------------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
知道我怎么解决这个问题?是不是可以制作某种复杂的索引,它会自动优先排序它们,然后选择匹配'Facebook'类型的前40个?它目前正在扫描超过500k行的表,然后返回一个非常低效的结果。
我一直在修改的其他一些版本的查询是:
select * from remote_request use index ( type_index,status_index,reserved_index,priority_index ) where remote_request.status = 'none' and type = 'Facebook' and reserv ed = '0' order by priority desc limit 0, 40
如果我们能够将扫描的行扫描到1000行以下,这将是惊人的,具体取决于有多少类型的请求进入表格。
先谢谢,除了最有经验的mysql专家外,对于大多数人来说,这可能是一个真正的胡桃夹子?
答案 0 :(得分:1)
这不是一个完整的答案,但评论太长了:
您实际上是在搜索所有这些索引吗?如果没有摆脱一些。额外的索引减慢了写入速度
其次在查询中使用EXPLAIN
,并且在执行时不指定索引。了解MySQL如何处理它而不是强制选择(通常它做正确的事情)。
最后排序可能会给你带来最大的伤害。如果你不排序它可能很快得到记录。它必须扫描并排序符合条件的每一行,然后才能返回前40名。
选项:
编辑我读了一些关于使用VIEW的内容,我不认为它会对你的情况有所帮助,因为你有这么大的表。请参阅此主题中的答案:Using MySQL views to increase performance
答案 1 :(得分:1)
您的四列索引具有正确的列,但顺序错误。
您希望索引首先查找匹配的行,您可以通过三列来查找。您正在查找三个相等条件,因此您知道一旦索引找到匹配行的集合,这些行的顺序基本上与前三列相关。因此,要解决这种关系,请将第四列添加到您想要排序的列。
如果你这样做,那么ORDER BY
就变成了无操作,因为查询只能按照它们存储在索引中的顺序读取行。
所以我会创建以下索引:
CREATE INDEX processing_order2 ON remote_request
(status, type, reserved, priority);
对前三列的顺序可能没有多大意义,因为它们都与AND
结合在一起。但priority
列属于最后一行。
您可能还想阅读我的演示文稿How to Design Indexes, Really。
顺便说一句,如果您拥有正确的索引,则不需要使用USE INDEX()
,MySQL的优化程序将在大多数情况下自动选择它。但是USE INDEX()
可以阻止优化器考虑您创建的新索引,因此它对代码维护来说是一个缺点。