我的网站上有一个查询(唯一不在DQL中的查询),这会减慢我正在处理的其中一个网站。基本上,该表是用户在网站上所做的事情的日志,以便我可以在实时订阅源上显示此信息。但是,它还需要组合这些行,以便如果用户上传多个图像,而不是每个图像都有一行,则会生成1行,其中列出了所有图像。
目前通过查询和迭代器完成此操作。查询获取该类型的最高行的ID和匹配的行数。然后代码将使用它来决定处理它的哪种类型的数据行,然后对它所告知的行数进行迭代。
表格
UserLog:
actAs:
Timestampable:
DmBlameable:
columns:
record_model: { type: string(255), notnull: true }
record_id: { type: integer, notnull: true }
record_created_by: { type: integer }
body: { type: string(255) }
is_active: { type: boolean, notnull: true, default: true }
privacy: { type: integer, default: 10 }
relations:
RecordCreatedBy:
class: DmUser
local: record_created_by
foreignAlias: UserLogs
查询:
SELECT MAX(id) AS id, count(*) AS numCondensed
FROM (SELECT t.*,
(SELECT count(*) FROM user_log u2
WHERE u2.id <= t.id
AND ( u2.record_model <> t.record_model
OR u2.created_by <> t.created_by
OR u2.body <> t.body) ) AS grp
FROM user_log t ) t
WHERE privacy <= 10 GROUP BY created_by, record_model, body, grp
ORDER BY `id` DESC
示例输出
id numCondensed
1806 1
1805 1
1804 11
1793 1
1792 1
1791 1
1790 1
1789 10
1779 1
1778 1
在一个有1700行(查询595行)的表上,这需要1.2秒才能运行。并且有6859行(来自查询的3300行),大约需要23秒。 WHERE子句中也有可能的选项,但它们不会接合以影响时序。在SELECTS和GROUP BY中使用的所有行都有索引。
我不反对制作表格/视图或完全重写它,只要对用户的结果视图是相同的。但我无法找到正确的方法来做任何这些并节省足够的时间。
代码是用Symfony 1.4编写的,原因是本地(1.2秒)的Doctrine和MYSQL 5.1以及实时(23秒)的5.5。
编辑 - 查询解释:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1725 Using where; Using temporary; Using filesort
2 DERIVED t ALL NULL NULL NULL NULL 1699
3 DEPENDENT SUBQUERY u2 ALL PRIMARY NULL NULL NULL 1699 Using where