Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用两列上的WHERE子句加速MySQL查询?_Mysql_Sql - Fatal编程技术网

如何使用两列上的WHERE子句加速MySQL查询?

如何使用两列上的WHERE子句加速MySQL查询?,mysql,sql,Mysql,Sql,我试图在两列上使用WHERE子句的大型表上加快查询速度,就我所能做到的而言,MySQL只使用ALERT_ID列 有没有办法使用这两个索引重写此查询 显示索引并解释下面的输出 show index from alert_hit; +-----------+------------+-------------------+--------------+-------------------+-----------+-------------+----------+--------+------+-

我试图在两列上使用WHERE子句的大型表上加快查询速度,就我所能做到的而言,MySQL只使用ALERT_ID列

有没有办法使用这两个索引重写此查询

显示索引并解释下面的输出

show index from alert_hit;

+-----------+------------+-------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name          | Seq_in_index | Column_name       | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+-------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| alert_hit |          0 | PRIMARY           |            1 | id                | A         |    15181402 |     NULL | NULL   |      | BTREE      |         |               |
| alert_hit |          1 | alert_id          |            1 | alert_id          | A         |          20 |     NULL | NULL   | YES  | BTREE      |         |               |
| alert_hit |          1 | timestamp         |            1 | timestamp         | A         |      446511 |     NULL | NULL   | YES  | BTREE      |         |               |
| alert_hit |          1 | data_source_id    |            1 | data_source_id    | A         |          20 |     NULL | NULL   | YES  | BTREE      |         |               |
| alert_hit |          1 | filter_syndicated |            1 | filter_syndicated | A         |          20 |     NULL | NULL   | YES  | BTREE      |         |               |
| alert_hit |          1 | unique_id         |            1 | unique_id         | A         |     5060467 |     NULL | NULL   | YES  | BTREE      |         |               |
| alert_hit |          1 | date_created      |            1 | date_created      | A         |      281137 |     NULL | NULL   |      | BTREE      |         |               |
| alert_hit |          1 | language          |            1 | language          | A         |          20 |     NULL | NULL   | YES  | BTREE      |         |               |
| alert_hit |          1 | region            |            1 | region            | A         |       42406 |     NULL | NULL   | YES  | BTREE      |         |               |
| alert_hit |          1 | market_rank       |            1 | market_rank       | A         |          20 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------+------------+-------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

explain select count(id) as history FROM alert_hit force index(alert_id, timestamp) where alert_id in (9045,9046,9047,9048,9049,9050,9051,9052,9330,9332)  AND timestamp between DATE_SUB( NOW(), INTERVAL 1*2 day) and DATE_SUB( NOW(), INTERVAL 1 day);
+----+-------------+-----------+-------+--------------------+----------+---------+------+-------+-------------+
| id | select_type | table     | type  | possible_keys      | key      | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+-------+--------------------+----------+---------+------+-------+-------------+
|  1 | SIMPLE      | alert_hit | range | alert_id,timestamp | alert_id | 5       | NULL | 99578 | Using where |
+----+-------------+-----------+-------+--------------------+----------+---------+------+-------+-------------+

两个字段都需要一个索引

ALTER TABLE alert_hit ADD INDEX `IDX-alert_id-timestamp` (`alert_id`, `timestamp`);
此外,MySQL将使用多列索引,直到在WHERE子句中有范围条件的第一个字段,因此在这种情况下,顺序很重要,
timestamp
应该是索引中的最后一个字段


正如@spencer7593所建议的那样,选择
COUNT(1)
而不是
COUNT(id)
可能也会更好。

我认为MySQL查询每个表只能使用一个索引。可以尝试使用这两个列创建另一个索引…或者,在
(alert\u id,timestamp,id)
上创建一个覆盖索引,该索引包含查询中引用的所有列(首先在WHERE子句中引用列)在解释输出的额外列中查找“Using index”(使用索引),以查看在不引用数据页的情况下索引是否满足查询要求。您可能还希望在索引中包含
id
列;这将允许“使用索引”满足查询,而无需引用数据页。或者,如果我们知道
id
不为空,则将查询更改为从…(中)选择COUNT(1),MySQL可以使用
(alert\u id,timestamp)
上的索引作为覆盖索引。这在InnoDB中是冗余的(它已经在索引的末尾),如果是MyISAM,则可以执行COUNT(*)并获得“使用索引”。是的,冗余。但是
(alert\u id,timestamp)
上的索引不是MySQL 5.1.38下InnoDB的OP查询的覆盖索引。(它是一个
选择计数(1)
的覆盖索引。我还在MySQL 5.5.25下使用InnoDB进行了测试,该索引是OP查询的覆盖索引,没有(冗余)添加id列。在MySQL 5.1 InnoDB上,覆盖索引的性能优势超过了“冗余”的成本索引中包含PK列。鉴于九个二级索引,OP似乎不关心存储“冗余”PK列。