如何使用DataMapper更好地优化多对多关联查询?

发布于 2024-11-03 20:15:51 字数 1591 浏览 0 评论 0原文

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_idINNER JOIN lefts ON joins.left_id = lefts.idWHERE joins.left_id = 1GROUP 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_idINNER JOIN lefts ON joins.left_id = lefts.idWHERE joins.left_id = 1GROUP BY rights.id, rights.one, rights.twoORDER 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't GROUP 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

放我走吧 2024-11-10 20:15:51

如何删除 Join 类定义,并将 Left 定义为:

class Left
  include DataMapper::Resource

  property :id, Serial

  has n, :rights, :through => Resource
end

相信 DM,它会为您创建良好的映射。

How about removing Join class definition, and defining Left as:

class Left
  include DataMapper::Resource

  property :id, Serial

  has n, :rights, :through => Resource
end

Believe DM, it creates good mapping for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文