获取 Count(*) 与实际数据对性能有影响
Getting Count(*) vs Actual Data has performance implications
我无法理解以下两个查询。第一个只获取整个结果集的计数。
第二个获取实际数据,但将结果集限制为 10 行。
- 不知何故第一个不能使用索引。我试过
USE INDEX (
timestamp_index,
Fulltext_title,
Fulltext_description)
没有用。
- count 查询不需要 order by ,但我只是想看看它是否可以那样使用索引。
- 据我所知,WHERE 子句是相同的,据我所知这是选择索引的最大因素。
获取计数
SELECT count(*) as total FROM table1
WHERE 1=1
AND type in ('category1','category3','category2')
AND (
MATCH(title) AGAINST (' +"apple"' IN BOOLEAN MODE)
OR
MATCH(description) AGAINST (' +"apple"' IN BOOLEAN MODE)
)
ORDER BY timestamp DESC
;
+-------+
| total |
+-------+
| 798 |
+-------+
1 row in set (3.75 sec)
解释扩展
+----+-------------+----------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | table1 | ALL | NULL | NULL | NULL | NULL | 669689 | 100.00 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+--------+----------+-------------+
获取实际结果
SELECT id, title,desciption,timestamp FROM table1
WHERE 1=1
AND type in ('category1','category3','category2')
AND (
MATCH(title) AGAINST (' +"apple"' IN BOOLEAN MODE)
OR
MATCH(description) AGAINST (' +"apple"' IN BOOLEAN MODE)
)
ORDER BY timestamp DESC
LIMIT 0, 10 ;
一组 10 行(0.06 秒)
解释扩展
+----+-------------+----------+-------+---------------+------+---------+------+------+------------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+-------+---------------+------+---------+---- --+------+------------+-------------+
| 1 | SIMPLE | table1 index | NULL | timestamp_index | 21 | NULL | 10 | 6696890.00 | Using where |
+----+-------------+----------+-------+---------------+------+---------+------+------+------------+-------------+
关于第二次查询。您需要前 10 个元素。因此优化器使用时间戳索引,对 table 进行排序并继续检查行,直到找到 10 个与您的 WHERE
匹配的元素
在您的第一个查询中,数据库必须扫描整个数据库以找到与您的查询匹配的元素,因此您的 ORDER BY
无济于事,因为您想要计算与您所在位置匹配的总行数。
现在还取决于您如何定义索引。 Type
、Title
和 Description
有一个索引吗?你有复合索引吗?
查这个MySQL索引TIPS
我找到了答案...我结合了两个索引。所以我们不必仅仅因为我们正在做一个计数(*)
就进行完整的table扫描
SELECT count(*) as total FROM table1 WHERE 1=1
AND type in ('category1','category2','category3')
AND MATCH(title, description) AGAINST (' +"apple"' IN BOOLEAN MODE)
;
+----+-------------+----------+----------+----------------------+----------------------+---------+------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+----------+----------------------+----------------------+---------+------+------+----------+-------------+
| 1 | SIMPLE | table1 | fulltext | FT_title_description | FT_title_description | 0 | NULL | 1 | 100.00 | Using where |
+----+-------------+----------+----------+----------------------+----------------------+---------+------+------+----------+-------------+
+-------+
| total |
+-------+
| 798 |
+-------+
1 row in set (0.83 sec)
我无法理解以下两个查询。第一个只获取整个结果集的计数。
第二个获取实际数据,但将结果集限制为 10 行。
- 不知何故第一个不能使用索引。我试过
USE INDEX (
timestamp_index,
Fulltext_title,
Fulltext_description)
没有用。 - count 查询不需要 order by ,但我只是想看看它是否可以那样使用索引。
- 据我所知,WHERE 子句是相同的,据我所知这是选择索引的最大因素。
获取计数
SELECT count(*) as total FROM table1
WHERE 1=1
AND type in ('category1','category3','category2')
AND (
MATCH(title) AGAINST (' +"apple"' IN BOOLEAN MODE)
OR
MATCH(description) AGAINST (' +"apple"' IN BOOLEAN MODE)
)
ORDER BY timestamp DESC
;
+-------+
| total |
+-------+
| 798 |
+-------+
1 row in set (3.75 sec)
解释扩展
+----+-------------+----------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | table1 | ALL | NULL | NULL | NULL | NULL | 669689 | 100.00 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+--------+----------+-------------+
获取实际结果
SELECT id, title,desciption,timestamp FROM table1
WHERE 1=1
AND type in ('category1','category3','category2')
AND (
MATCH(title) AGAINST (' +"apple"' IN BOOLEAN MODE)
OR
MATCH(description) AGAINST (' +"apple"' IN BOOLEAN MODE)
)
ORDER BY timestamp DESC
LIMIT 0, 10 ;
一组 10 行(0.06 秒)
解释扩展
+----+-------------+----------+-------+---------------+------+---------+------+------+------------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+-------+---------------+------+---------+---- --+------+------------+-------------+
| 1 | SIMPLE | table1 index | NULL | timestamp_index | 21 | NULL | 10 | 6696890.00 | Using where |
+----+-------------+----------+-------+---------------+------+---------+------+------+------------+-------------+
关于第二次查询。您需要前 10 个元素。因此优化器使用时间戳索引,对 table 进行排序并继续检查行,直到找到 10 个与您的 WHERE
在您的第一个查询中,数据库必须扫描整个数据库以找到与您的查询匹配的元素,因此您的 ORDER BY
无济于事,因为您想要计算与您所在位置匹配的总行数。
现在还取决于您如何定义索引。 Type
、Title
和 Description
有一个索引吗?你有复合索引吗?
查这个MySQL索引TIPS
我找到了答案...我结合了两个索引。所以我们不必仅仅因为我们正在做一个计数(*)
就进行完整的table扫描SELECT count(*) as total FROM table1 WHERE 1=1
AND type in ('category1','category2','category3')
AND MATCH(title, description) AGAINST (' +"apple"' IN BOOLEAN MODE)
;
+----+-------------+----------+----------+----------------------+----------------------+---------+------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+----------+----------------------+----------------------+---------+------+------+----------+-------------+
| 1 | SIMPLE | table1 | fulltext | FT_title_description | FT_title_description | 0 | NULL | 1 | 100.00 | Using where |
+----+-------------+----------+----------+----------------------+----------------------+---------+------+------+----------+-------------+
+-------+
| total |
+-------+
| 798 |
+-------+
1 row in set (0.83 sec)