我们正面临与选择查询相关的性能问题。 我们有报告表,其中包含大约 2千万(2000万)的记录。
当我们执行简单计数(*)从检查计数时,它需要超过1分钟才能显示结果。
以下是有关mysql,服务器和查询的信息
系统信息
OS : Debian 6.0.7
Model : AMD Opteron(tm) Processor 6172
cpu MHz : 2100.154
cache size : 512 KB
processor : 2
Memory total used free shared buffers cached
Mem: 16083 6335 9747 0 153 5323
Mysql信息
mysql Ver 14.14 Distrib 5.1.66, for debian-linux-gnu (x86_64) using readline 6.1
my.conf设置
key_buffer = 16M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
max_connections = 1000
table_cache = 128
innodb_buffer_pool_size = 3G
query_cache_limit = 512M
query_cache_size = 3G
mysql> select count(*) from reports;
+-----------+
| count(*) |
+-----------+
| 23311587 |
+-----------+
1 row in set (67.07 sec)
DB engine : Innodb
。
编辑:使用索引执行查询而不使用索引
mysql> select count(id) from Reports USE INDEX(PRIMARY);
+-----------+
| count(id) |
+-----------+
| 17835433 |
+-----------+
1 row in set (55.56 sec)
mysql>
mysql> select count(id) from Reports;
+-----------+
| count(id) |
+-----------+
| 17835433 |
+-----------+
1 row in set (55.65 sec)
我正在努力解决性能问题,有谁可以帮助我提高表的性能?
答案 0 :(得分:1)
答案 1 :(得分:1)
这是因为您使用的是InnoDB。
InnoDB表在简单的count(*)查询上很慢,因为它需要对其执行全表扫描。
通过使用PRIMARY索引,您可以提高此查询的性能。
select count(reportId) from reports USE INDEX(PRIMARY);
这里真正的问题是:你需要经常执行这种查询吗?大多数情况下,你会使用WHERE子句进行计数,在给定正确的索引的情况下,它应该运行得很好
答案 2 :(得分:1)
答案 3 :(得分:0)
MySQL通过实际查看数据来执行count(*)
。如果您有主键索引,它将扫描主键索引以获取结果,而不是原始数据。令我印象深刻的是,你的系统性能如此一致,以至于同一操作在一种情况下需要55.56秒而在另一种情况下需要55.65秒 - 差异不到半个百分点。
执行扫描需要将索引加载到内存中。如果索引不适合内存,则需要更长时间。检查系统内存配置,确保一次可以容纳1700万条记录。唉,我并不熟悉配置MySQL的所有参数,但是在具有16 GB内存和3Gbytes缓冲池的机器上,应该有足够的内存。
如果此类查询的性能很重要,您可能需要考虑其他选项。对具有1700万行的表进行即席查询需要时间。如果您需要速度性能,请考虑采用数据集市方法,以解决大多数用户问题的方式提取和汇总数据。