trans_tbl
正在使用Aria DB引擎我对该数据库表应用了索引,如下所示:
evt_id
transaction_type
为什么执行以下操作时会忽略transaction_type
索引?
SELECT COUNT(evt_id), transaction_type FROM trans_tbl GROUP BY transaction_type
如果我查看EXPLAIN
的输出,就会看到:
MariaDB [my_db]> EXPLAIN SELECT COUNT(evt_id), transaction_type FROM trans_tbl GROUP BY transaction_type;
+------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
| 1 | SIMPLE | trans_tbl | ALL | NULL | NULL | NULL | NULL | 126006123 | Using temporary; Using filesort |
+------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
这让我感到困惑的是,查询中的两者都已建立索引。因此,不应该利用索引吗?
为什么在以下情况下使用transaction_type
索引,为什么我所做的一切都从COUNT(evt_id)
(主键)切换了?到COUNT(1)
。 (该列为transaction_type
,从该列生成的索引称为TransType
。)
MariaDB [my_db]> EXPLAIN SELECT COUNT(1), transaction_type FROM trans_tbl GROUP BY transaction_type;
+------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
| 1 | SIMPLE | trans_tbl | index | NULL | TransType | 35 | NULL | 126006123 | Using index |
+------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
第一个查询(带有COUNT(evt_id)
)耗时2分40秒。由于未使用索引,因此很有意义。但是第二个查询(使用COUNT(1)
)需要50秒。这对我来说毫无意义。基本上不应该花0秒吗?难道不能只看每组的第一个和最后一个索引值,然后减去它们并计数吗?在我看来,它实际上确实在计数。索引的意义是什么?
PS我知道对于这种大小的DB表,该机器的功能不足。但是,表数据不值得花很多钱来提高性能。我宁愿学习适当地实现Aria索引以提高速度。
答案 0 :(得分:1)
COUNT(x)
在对行进行计数之前检查x
是否为NOT NULL
。
COUNT(*)
是计数行的常用模式。
所以...
SELECT COUNT(evt_id), transaction_t is just `SELECT FIND_IN_SET(17, '8,12,17,90');`ype
FROM trans_tbl GROUP BY transaction_type;
决定进行表格扫描,然后进行排序和分组。
SELECT COUNT(*), transaction_type
FROM trans_tbl GROUP BY transaction_type;
看到INDEX(transaction_type)
并说“天哪;我可以扫描该索引而不必进行排序”。注意:它仍然必须扫描才能计数。但是INDEX
比表小,因此可以更快地完成。这也称为“覆盖”索引,因为SELECT
中所需的所有列都位于该INDEX
中。
COUNT(1)
可能与COUNT(*)
一样,我不知道。
INDEX(transaction_type)
与INDEX(transaction_type, evt_id)
基本相同。这是因为PRIMARY KEY
被默默地附加到InnoDB中的任何辅助键上。
我不知道为什么不使用INDEX(transaction_type, evt_id)
。底线:使用COUNT(*)
。
为什么不是0秒?计数不会保存在任何地方。无论如何,当您运行SELECT
时,可能会有其他查询修改计数。改进来自扫描126M的2列行,而不是126M的多列行。