提高查询生成历史记录的效果

时间:2018-03-02 13:01:37

标签: mysql performance query-performance entity-attribute-value

我已实现了跟踪对数据库中存储的项目所做更改的功能。让我们看一下产品许可证,例如存储在表dp_tech_licence(主键LicenceId)中。

每当更改许可证时,更改都会存储在表格dp_tech_licence_history_mod(主键ModificationId),dp_tech_licence_history(主键HistoryId)和{{1} }(主键dp_history)。 CollectionId对于已更改的许可证的每个属性都有一行,并且具有引用dp_tech_licence_history_mod的外键HistoryId。对于每个已更改的许可,dp_tech_licence_history都有一行,并且引用dp_tech_licence_history的外键CollectionId和引用dp_history的外键LicenceIddp_tech_licence每次应用一项或多项更改时都有一行,并且外键dp_history引用UserId(表示执行更改的人员)。

例如,当为用户分配许可证时,dp_user会更改。这将导致每个表dp_tech_licence.UserIddp_tech_licence_history_moddp_tech_licence_history中的一个新行。对于dp_history中的新行,我们的值为dp_tech_licence_history_modProperty = 'UserId',其中Value = '<id>'是用户的ID。

完成所有这些后,我想查看特定用户的许可证历史记录。具体来说,我想知道:

  1. 每次为用户分配许可时(<id>更改为用户的ID)
  2. 每次从用户移除许可时(dp_tech_licence.UserId已从用户的ID更改
  3. 为避免存储冗余数据,只有属性更改为的值存储在dp_tech_licence.UserId中,而不是属性更改的值。因此,找出何时从用户移除许可证(上面的第2点)并不是直截了当的。我提出了以下问题,其中dp_tech_licence_history_mod是用户的ID:

    <id>

    条件指出SELECT * FROM dp_tech_licence_history_mod t1 LEFT JOIN dp_tech_licence_history t2 ON t2.`HistoryId` = t1.`HistoryId` LEFT JOIN dp_history t3 ON t3.`CollectionId` = t2.`CollectionId` WHERE t1.`Property` = 'UserId' AND ('<id>' = t1.`Value` OR '<id>' = ( SELECT t4.`Value` FROM dp_tech_licence_history_mod t4 LEFT JOIN dp_tech_licence_history t5 ON t5.`HistoryId` = t4.`HistoryId` LEFT JOIN dp_history t6 ON t6.`CollectionId` = t5.`CollectionId` WHERE t4.`Property` = 'UserId' AND t5.`LicenceId` = t2.`LicenceId` AND t6.`ModifiedDate` < t3.`ModifiedDate` ORDER BY t6.`ModifiedDate` DESC LIMIT 1 )) ORDER BY t3.`ModifiedDate` DESC 是用户的ID,或者上次dp_tech_licence_history_mod.Value已针对同一许可进行了更改,它已设置为用户的ID(这意味着它现在已从用户的ID更改为其他内容。

    这个查询似乎工作正常,但它真的很慢!大约需要1.5秒,UserId的行数少于20,000行。我想我已经添加了所有索引。以下是表格定义:

    dp_tech_licence_history_mod

    以下是运行CREATE TABLE `dp_tech_licence_history_mod` ( `ModificationId` bigint(32) NOT NULL AUTO_INCREMENT, `HistoryId` bigint(32) NOT NULL, `LocaleId` bigint(32) DEFAULT NULL, `Property` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `Value` text COLLATE utf8mb4_unicode_ci, PRIMARY KEY (`ModificationId`), KEY `dp_tech_licence_history_mod_History` (`HistoryId`), KEY `dp_tech_licence_history_mod_Locale` (`LocaleId`), KEY `dp_tech_licence_history_mod_Property` (`Property`), CONSTRAINT `dp_tech_licence_history_mod_ibfk_1` FOREIGN KEY (`HistoryId`) REFERENCES `dp_tech_licence_history` (`HistoryId`), CONSTRAINT `dp_tech_licence_history_mod_ibfk_2` FOREIGN KEY (`LocaleId`) REFERENCES `dp_locale` (`LocaleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci CREATE TABLE `dp_tech_licence_history` ( `HistoryId` bigint(32) NOT NULL AUTO_INCREMENT, `CollectionId` bigint(32) NOT NULL, `TypeId` bigint(32) NOT NULL, `LicenceId` bigint(32) NOT NULL, PRIMARY KEY (`HistoryId`), KEY `dp_tech_licence_history_Licence` (`LicenceId`), KEY `dp_tech_licence_history_Collection` (`CollectionId`), KEY `dp_tech_licence_history_Type` (`TypeId`), CONSTRAINT `dp_tech_licence_history_Type` FOREIGN KEY (`TypeId`) REFERENCES `dp_history_type` (`TypeId`), CONSTRAINT `dp_tech_licence_history_ibfk_2` FOREIGN KEY (`LicenceId`) REFERENCES `dp_tech_licence` (`LicenceId`), CONSTRAINT `dp_tech_licence_history_ibfk_3` FOREIGN KEY (`CollectionId`) REFERENCES `dp_history` (`CollectionId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci CREATE TABLE `dp_history` ( `CollectionId` bigint(32) NOT NULL AUTO_INCREMENT, `ModifierId` bigint(32) DEFAULT NULL, `ModifiedDate` datetime NOT NULL, `Uri` text COLLATE utf8mb4_unicode_ci, PRIMARY KEY (`CollectionId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

    的结果
    EXPLAIN

    有没有人知道我如何才能提高跟踪更改的实施效果?

0 个答案:

没有答案