我在wamp服务器上运行了一个mysql数据库,我用它来对Flickr数据进行频繁的模式挖掘。在将数据加载到数据库的过程中,我运行了一个计数查询来确定我已经加载了多少图像。
我花了3分49秒才感到惊讶select count(*) from image;
在另一个表格" concept"中,我存储了用户提供图片的标签列表。关于"概念的类似查询"桌上花了0.8秒。神秘之处在于两个表都有大约200,000行。 select count(*) from image;
返回283,890,select count(*) from concept;
返回213,357。
这里是每个表格的描述
显然"图像"表有更大的行。我想也许"图像"根据{{3}},内存太大而无法保存在内存中,因此我还使用this blog post中的代码测试了表的大小。
SELECT table_name AS "Tables",
round(((data_length + index_length) / 1024 / 1024), 2) "Size in MB"
FROM information_schema.TABLES
WHERE table_schema = "$DB_NAME"
ORDER BY (data_length + index_length) DESC;
"图像"是179.98 MB,"概念"是15.45 MB
我在拥有64 GB RAM的计算机上运行mysql,因此这两个表都应该很容易适应。我错过了什么会减慢我的查询速度?我该如何解决?
答案 0 :(得分:6)
在InnDB表上执行SELECT COUNT(*)
时,MySQL必须扫描索引以计算行数。在这种情况下,您唯一的索引是主(聚集)索引,因此MySQL会扫描该索引。
对于聚簇索引,实际的表数据也存储在那里。不包括开销,您的image
表每行约为1973字节(我假设两个主键列都有单字节字符集)。这是每(16k)页最多8条记录,因此大约35,486页。您的comcept
表每行大约257个字节。那个页面大约有63个记录,所以大约有3,386页。这是必须扫描的数据量的巨大差异。
它必须完全读取每个页面,因为页面可能不完整。
然后,表现明智,也许这些页面中的一些是在内存中而有些则不是。由于MySQL的15/16偏好,也存在一些边际差异,但上述所有数字都应视为近似值。
<强>解决方案强>
向较大的表添加辅助索引应该会产生与较小的表大致相同的SELECT COUNT(*)
性能。当然,要更新另一个索引,更新会慢一些。
为了提高性能,请缩短主键,因为二级索引包括索引列和完整主键。
如果您只需要估计的行数,则可以使用以下某个值中的rows
值,该值使用表统计信息而不是扫描索引:
SHOW TABLE STATUS LIKE 'image'
或
EXPLAIN SELECT COUNT(*) FROM image
答案 1 :(得分:1)
如果你正在寻找一个球场号而不是一个确切的数,那么来自show table status
的Rows列可能就足够了。 InnoDB表格并不总是准确的,但无论如何,您似乎还可以粗略估计。