Как мне лучше оптимизировать запросы на сопоставление многие-ко-многим с помощью DataMapper? - PullRequest
4 голосов
/ 27 апреля 2011

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_idINNER JOIN lefts ON joins.left_id = lefts.idWHERE joins.left_id = 1GROUP BY rights.id, rights.one, rights.twoORDER 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 идет по тому же маршруту и ​​выполняет два запросавыше.

1 Ответ

3 голосов
/ 06 ноября 2011

Как насчет удаления определения класса Join и определения Left как:

class Left
  include DataMapper::Resource

  property :id, Serial

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

Поверьте, DM создает хорошее отображение для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...