1
+----------------------------+------------------------------------------------------------------------------+------+-----+---------+----------------+
| 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      |         |               |
+----------------+------------+----------------------------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

知道我如何解决这个问题吗?是否不可能制作某种复杂的索引来自动对它们进行优先排序,然后取前 40 个与“Facebook”类型匹配的索引?它目前正在扫描超过 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 专家吗?

4

2 回答 2

1

这不是一个完整的答案,但评论太长了:

您实际上是在搜索所有这些索引吗?如果不摆脱一些。额外的索引会减慢写入速度。

其次EXPLAIN,在您的查询中使用,并且在您这样做时不要指定索引。看看 MySQL 如何处理它而不是强制一个选项(通常它做正确的事情)。

最后排序可能是最伤害你的。如果你不排序,它可能很快就会得到记录。它必须扫描和排序符合您条件的每一行,然后才能返回前 40 名。

选项:

  1. 尝试创建一个 VIEW(对 VIEWS 不太熟悉,但它可能会起作用)
  2. 将此表拆分为较小的表
  3. 使用第三方工具(例如 Sphinx 或 Lucene)来创建专门的索引以进行搜索。(我以前用过 Sphinx 来做类似的事情。你可以在 http://sphinxsearch.com/找到它)。
  4. 或者考虑使用 NoSQL 解决方案,您可以在其中使用 Map 函数来执行此操作。

编辑我读了一些关于使用 VIEW 的文章,我认为它对你的情况没有帮助,因为你有这么大的桌子。请参阅此线程中的答案:使用 MySQL 视图提高性能

于 2013-08-25T06:25:32.477 回答
1

您的四列索引具有正确的列,但顺序错误。

您希望索引首先查找匹配的行,您可以按三列执行此操作。您正在通过三个相等条件进行查找,因此您知道一旦索引找到匹配行的集合,这些行的顺序基本上与前三列是平局的。因此,要解决平局,请将要排序的列添加为第四列。

如果你这样做,那么就ORDER BY变成了无操作,因为查询可以按照它们在索引中存储的顺序读取行。

所以我会创建以下索引:

CREATE INDEX processing_order2 ON remote_request 
 (status, type, reserved, priority);

前三列的顺序可能没有太大意义,因为它们都是在相等条件下加上AND. 但该priority列属于最后。

您可能还想阅读我的演示文稿如何设计索引,真的

顺便说一句,USE INDEX()如果您有正确的索引,则不需要使用,MySQL 的优化器大部分时间会自动选择它。但是USE INDEX()会阻止优化器考虑您创建的新索引,因此它对代码维护不利。

于 2013-08-25T06:43:51.463 回答