获取 Count(*) 与实际数据对性能有影响

Getting Count(*) vs Actual Data has performance implications

我无法理解以下两个查询。第一个只获取整个结果集的计数。

第二个获取实际数据,但将结果集限制为 10 行。

获取计数

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 无济于事,因为您想要计算与您所在位置匹配的总行数。

现在还取决于您如何定义索引。 TypeTitleDescription 有一个索引吗?你有复合索引吗?

查这个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)