MySQL - 带有 IN 子句的查询表现不佳

标签 mysql performance entity-attribute-value

我有一个包含四个表(项目、属性、快照和值)的 MySQL 数据库。基本上, 表包含给定特定日期(快照)的项目 的特定属性 的值。

enter image description here

包含以下列

  • value_id
  • FK_itemid(项目的外键)
  • FK_propertyid(属性的外键)
  • FK_snapshotid(快照的外键)
  • 值(作为字符串)

现在我想为所有其他属性具有特定值的项目获取某个属性 (-id) 的值:

SELECT * FROM
            (SELECT * FROM remian.remian_propertyvalue WHERE 
                                            FK_ItemId IN (SELECT FK_ItemId FROM (SELECT * FROM remian.remian_propertyvalue WHERE FK_PropertyId=1) AS trackerentries WHERE trackerentries.Value IN (12,11) AND
                                            FK_ItemId IN (SELECT FK_ItemId FROM (SELECT * FROM remian.remian_propertyvalue WHERE FK_PropertyId=12) AS statustable WHERE statustable.Value NOT IN ("Rejected","Closed")) AND
                                            FK_ItemId IN (SELECT FK_ItemId FROM (SELECT * FROM remian.remian_propertyvalue WHERE FK_PropertyId=2) AS projectentries WHERE projectentries.Value IN (73,74)))) AS queried
WHERE queried.FK_PropertyId=12 AND FK_SnapshotId = 1;

此查询确实有效,但速度非常慢(5000 个条目需要 80 秒)。有没有更有效的方法来做到这一点?

最佳答案

EAV 模式使用起来非常困惑。使用 IN ( SELECT ... ) 只会让它变得更糟和更慢

你需要尝试不使用子查询,只使用JOINs,比如

SELECT *
    FROM remian_propertyvalue AS a
    JOIN remian_propertyvalue AS b  USING(FK_ItemId)
    JOIN remian_propertyvalue AS c  USING(FK_ItemId)
    WHERE a.FK_PropertyId = 1  AND a.value IN (12,11)
      AND b.FK_PropertyId = 12 AND b.value IN ("Rejected","Closed")
      AND c.FK_PropertyId = 2  AND c.value IN (73,74)
      AND a.FK_PropertyId = 12 AND a.FK_SnapshotId = 1;

此外,“property”表上没有AUTO_INCREMENT。取而代之的是

PRIMARY KEY(itemId, propertyId),
INDEX(propertyId, value)

这些索引可能存在问题;我真的需要查看 SHOW CREATE TABLE 来提供帮助。

更多:

关于MySQL - 带有 IN 子句的查询表现不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49450001/

相关文章:

没有键/索引的 MYSQL 连接表

mysql - Ansible - 在 array 上循环由 shell 命令产生

mysql - 如何将mysql的默认端口从3306更改为3360

css - 浮点值对 CSS 属性的性能影响

使用TFS 2013普通版进行性能测试

mysql - 我应该在大型 EAV 表中使用时间戳还是单独的时间列?

sql-server - 更新 EAV 表行的最佳实践

mysql - 将两列合并为一列

c++ - 是否可以直接保留并复制到 std::string 中?

MySQL:将 1:m 的所有值放入一个字段中?