如何使用DataMapper更好地优化多对多关联查询?
DataMapper 似乎正在为使用连接表的关联生成严重次优的查询。我可以做什么来提高这些查询的性能?请注意,它也使用隐式连接表生成相同的查询(:through => Resource
)
这是我的设置:
class Left
include DataMapper::Resource
property :id, Serial
has n, :joins
has n, :rights, :through => :joins
end
class Join
include DataMapper::Resource
belongs_to :left, :key => true
belongs_to :right, :key => true
end
class Right
include DataMapper::Resource
property :id, Serial
property :one, String
property :two, Integer
end
现在,假设我填充了一些数据,并且我想获取所有权限与左对象关联:
Left.first.rights
DataMapper 执行以下查询:
SELECTrights.id,rights.one,rights.twoFROMrightsINNERJOIN joinsONrights.id=joins.right_id
INNER JOIN lefts ON joins.left_id = lefts.id
WHERE joins.left_id = 1
GROUP BY right.id、rights.one、rights。两个
ORDER BYrights.id
DataMapper正在生成一个完全不必要的
JOIN
(第一个粗体部分)。我不相信我的 RDBMS (MySQL) 会聪明地忽略这一点。它至少在解释计划中显示为“使用索引;使用临时;使用文件排序”。GROUP BY
是怎么回事?这里似乎完全没有必要 - 由于连接表上的复合键,我不能有重复项。另外,GROUP BY Rights.id
不会有同样的效果吗?或者甚至更好,SELECT DISTINCT
这些查询非常慢(在两侧都有更多属性的表上),并且我不确定如何正确索引表来支持它。
从连接模型查询要快得多:Join.all(:left => Left.first).rights
,尽管它执行两个语句:
SELECT right_id FROM joins WHERE left_id = 1
SELECT id, one, two FROM rights WHERE id = 1 ORDER BY id
有趣的是,Left.first.joins .rights
采用相同的路线并执行上面的两个查询。
DataMapper appears to be generating grossly sub-optimal queries for associations that use a join table. What can I do to improve the performance of these queries? Note that it generates the same queries with an implicit join table, as well (:through => Resource
)
Here's my setup:
class Left
include DataMapper::Resource
property :id, Serial
has n, :joins
has n, :rights, :through => :joins
end
class Join
include DataMapper::Resource
belongs_to :left, :key => true
belongs_to :right, :key => true
end
class Right
include DataMapper::Resource
property :id, Serial
property :one, String
property :two, Integer
end
Now, say I have some data populated and I want to grab all the rights associated with a left object:
Left.first.rights
DataMapper executes the following query:
SELECT rights.id, rights.one, rights.two FROM rights INNER JOIN joins ON rights.id = joins.right_id
INNER JOIN lefts ON joins.left_id = lefts.id
WHERE joins.left_id = 1
GROUP BY rights.id, rights.one, rights.two
ORDER BY rights.id
DataMapper is generating a completely unnecessary
JOIN
(first bold section). I don't trust my RDBMS (MySQL) to be smart about ignoring this. It shows up in the explain plan, as "Using index; Using temporary; Using filesort", at least.What's up with the
GROUP BY
? It also seems completely unnecessary here - due to the composite key on the join table, I can't have duplicates. Plus, wouldn'tGROUP BY rights.id
have the same effect? Or even better,SELECT DISTINCT
These queries are extremely slow (on tables with more properties on both sides), and I'm not sure how to properly index the tables to support it.
It's far faster to query from the join model: Join.all(:left => Left.first).rights
, though it is performing two statements:
SELECT right_id FROM joins WHERE left_id = 1
SELECT id, one, two FROM rights WHERE id = 1 ORDER BY id
Interestingly, Left.first.joins.rights
goes the same route and executes the two queries above.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如何删除 Join 类定义,并将 Left 定义为:
相信 DM,它会为您创建良好的映射。
How about removing Join class definition, and defining Left as:
Believe DM, it creates good mapping for you.