问题描述我有一个审计表,其中包含一些对象的历史更改。审核包含唯一的审核事件id、要更改的对象id、更改日期、已更改的属性以及更改前后的值和其他列。
我需要做的是查询审计数据并获取同一对象上同一字段先前更改的日期。因此,我需要再看一次审计,并为每个审计条目添加上一个类似条目,其日期为上一个更改日期。
schema&data表schema以id(id)作为主键,以objectid(parent\ id)作为索引。其他的都没有索引。在我的测试用例中,我有大约150个对象,其中有大约80k个审计条目。
解决方案有两个明显的解决方案子查询和左连接。
在left join中,我基本上用join语句将同一个审计表再次连接到自身上,确保对象、字段和值的更改是一致的,更改早于当前更改,请选择“最大更改日期”,最后选择“仅拾取一个最新的上一个更改i按id分组”。如果未找到上一个更改,请使用对象本身的创建日期。左联接sql
SELECT `audit`.`id` AS `id`,
`audit`.`parent_id` AS `parent_id`,
`audit`.`date_created` AS `date_created`,
COALESCE(MAX(`audit_prev`.`date_created`), `audit_parent`.`date_entered`) AS `date_created_before`,
`audit`.`field_name` AS `field_name`,
`audit`.`before_value_string` AS `before_value_string`,
`audit`.`after_value_string` AS `after_value_string`
FROM `opportunities_audit` `audit`
LEFT JOIN `opportunities_audit` `audit_prev`
ON(`audit`.`parent_id` = `audit_prev`.`parent_id`
AND `audit_prev`.`date_created` < `audit`.`date_created`
AND `audit_prev`.`after_value_string` = `audit`.`before_value_string`
AND `audit`.`field_name` = `audit_prev`.`field_name`)
LEFT JOIN `opportunities` `audit_parent` ON(`audit`.`parent_id` = `audit_parent`.`id`)
GROUP BY `audit`.`id`;
子查询逻辑非常相似,但不是分组,而是使用max函数,我只有orderbydatedesc和limit1
SELECT `audit`.`id` AS `id`,
`audit`.`parent_id` AS `parent_id`,
`audit`.`date_created` AS `date_created`,
COALESCE((SELECT `audit_prev`.`date_created`
FROM `opportunities_audit` AS `audit_prev`
WHERE
(`audit_prev`.`parent_id` = `audit`.`parent_id`)
AND (`audit_prev`.`date_created` < `audit`.`date_created`)
AND (`audit_prev`.`after_value_string` = `audit`.`before_value_string`)
AND (`audit_prev`.`field_name` = `audit`.`field_name` )
ORDER BY `date_created` DESC
LIMIT 1
), `audit_parent`.`date_entered`) AS `date_created_before`,
`audit`.`field_name` AS `field_name`,
`audit`.`before_value_string` AS `before_value_string`,
`audit`.`after_value_string` AS `after_value_string`
FROM `opportunities_audit` `audit`
LEFT JOIN `opportunities` `audit_parent` ON(`audit`.`parent_id` = `audit_parent`.`id`);
两个查询产生相同的结果集。
问题当我在phpmyadmin中运行查询时,使用join的解决方案大约需要2个30秒才能返回结果。然而,phpmyadmin说这个查询花了0.04秒。当我运行子查询解决方案时,结果会立即返回,phpmyadmin报告的执行时间大约为0.06秒。
所以我很难理解实际执行时间的差异是从哪里来的。我最初的猜测是,问题可能与phpmyadmin对返回数据集的自动限制有关——虽然结果有80k行,但只显示25行。但是手动将限制添加到查询中会使它们执行得很快。
另外,从命令行mysql工具运行查询会返回两个查询的完整结果集,报告的执行时间与实际执行时间相对应,使用join的方法仍然比subquery快大约1.5倍。
从profiler数据来看,似乎大部分等待时间都花在了发送数据上。因为发送数据需要几分钟的时间,其他一切都需要几微秒的时间。
为什么phpmyadmin的行为在这两个查询中会有如此大的差异呢?
暂无答案!
目前还没有任何答案,快来回答吧!