【问题标题】:MySQL Partitioning Join Table (Dual PK)MySQL 分区连接表(双 PK)
【发布时间】:2013-11-20 04:10:51
【问题描述】:

我有两个表通过第三个表连接在一起。第一个表(图像)包含超过一百万条记录。第二个表(标签)包含大约 10 万条记录。第三张表是由image_id和tag_id组成的双主键表,大约有400万条记录。

我一直在尝试确定一种方法来加快按标签搜索图像的速度。在阅读了十几条记录之后,听起来我最好的选择是对我的连接表进行分区。不幸的是,我以前从未这样做过,并且害怕可能会破坏系统中最大的表。

无论如何,由于该表是一个双主键,它已编入索引,但查询仍然需要相当长的时间。我不确定是严格来说是该表的速度,还是我要加入的图像表的速度。无论哪种方式,截至目前,我的查询时间都达到了 2-3 秒,并且担心我会因为更多的图像、更多的标签和更多的用户而进一步陷入困境。

所有查找都是使用 INT(11) 主键完成的。我从不进行文本搜索,也从不查看 varchar 字段。一个查询确实查看了status CHAR(1) 列。当然,状态不是索引,但它应该是吗?我最初考虑使用 A、I、X、D 作为选项的 ENUM,但从那时起我已经扩展了多达 6 种状态类型。

硬件方面,我使用的是带有 24GB DDR3 的核心 i-7,而 MySQL 存在于 120GB 固态硬盘上(仅 3gbps)。

我可以做些什么来加快速度?是瓶颈磁盘io、查询效率、内存利用率差吗?

作为后续说明,我一直在通过 MySQL Workbench 观察服务器活动,发现了 2 件有趣的事情:

  1. 密钥效率为 99.99%,而查询缓存命中率为 0.28%。
  2. 我经常看到重新计算计数的 cron 作业的状态为“正在复制到 tmp 表”。

查询是:

SELECT COUNT(t.image_id) FROM Image_Tags t
INNER JOIN (Images i) ON (i.image_id = t.image_id)
WHERE t.tag_id = :tid
AND i.status = 'A'

我开始认为我需要在该状态列上添加一个索引。

【问题讨论】:

  • 那么你的连接表中的每一列都是一个键,或者你有一个包含两个字段的键?
  • 它是双主的,所以它们都是一个键。
  • 和常识刚刚开始......没有意识到您可以多次索引同一列。
  • 你运行EXPLAIN <you_query>了吗?发布结果。您的确切表模式如何?你在用什么引擎(MyISAM、InnoDB、...)?
  • 将 image_id 和 tag_id 添加为它们自己的单列索引大大缩短了响应时间。它们都是 InnoDB 表。 '1', 'SIMPLE', 't', 'ref', 'PRIMARY,tag_id,image_id', 'tag_id', '4', 'const', '27950', '使用索引' '1', 'SIMPLE ', 'i', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'DB.t.image_id', '1', '使用 where'

标签: php mysql mysql-workbench


【解决方案1】:

问题是双主键。作为对偶,它基本上必须查看连接表中的每条记录。我为 tag_id 添加了一个键,为 image_id 添加了一个键,它大大提高了速度。谢谢马哈维蒂!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 2023-04-01
    • 2018-10-29
    • 2012-02-10
    • 2012-02-13
    • 2011-09-08
    • 2013-05-15
    相关资源
    最近更新 更多