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执行以下查询:
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正在生成一个完全不必要的JOIN
(第一个粗体部分)。我不相信我的RDBMS(MySQL)能够聪明地忽略这一点。它在解释计划中显示为“使用索引;使用临时;使用filesort”,至少。
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
采用相同的路线并执行上述两个查询。
答案 0 :(得分:3)
如何删除Join类定义,并将Left定义为:
class Left
include DataMapper::Resource
property :id, Serial
has n, :rights, :through => Resource
end
相信DM,它为您创建了良好的映射。