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
(первый жирный раздел).Я не верю, что моя СУБД (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
идет по тому же маршруту и выполняет два запросавыше.