MySQL адаптер datamapper объединяет запросы вместо объединения - PullRequest
2 голосов
/ 16 июля 2011

Я использую DataMapper (гем ruby) в качестве ORM для базы данных mysql. (dm-core 1.1.0, do-mysql-adapter 1.1.0, do_mysql 0.10.6)

Я пишу приложение, в котором есть две таблицы: журнал использования диска с течением времени и таблица «текущего использования», содержащая внешние ключи, с «последним» использованием диска для удобства. Классы DataMapper: Quota и LatestQuota, с простой схемой:

class Quota
  include DataMapper::Resource

  property :unique_id, Serial, :key => true
  property :percentage, Integer
  ... (more properties)
end

class LatestQuota
  include DataMapper::Resource
  belongs_to :quota, :key => true
end

В моем коде я хочу найти все записи в таблице LatestQuota, которые соответствуют квоте с процентом выше 95. Я использую следующий запрос datamapper:

quotas = LatestQuota.all(:quota => {:percentage.gte => threshold})
...later...
quotas.select{|q| some_boolean_function?(q)}

Принимая во внимание, что some_boolean_function отфильтровывает результаты таким образом, о котором DataMapper не может знать, поэтому мне нужно вызывать метод ruby ​​select ().

Но в конечном итоге он вызывает следующие SQL-запросы (сообщается в результатах отладки DM):

SELECT `unique_id` FROM `quota` WHERE `percentage` >= 95

затем позже:

SELECT `quota_unique_id` FROM `latest_quota` 
WHERE `quota_unique_id` IN (52, 78, 82, 232, 313, 320…. all the unique id's from the above query...)

Это смехотворно неоптимальный запрос, поэтому я думаю, что делаю что-то не так. В таблице quota содержатся миллионы записей (исторических данных) по сравнению с примерно 15 000 записей в latest_quota, и выбор сначала всех quota записей, а затем выбор latest_quota записей из результатов является совершенно неправильным способом сделать это.

Я хотел бы, чтобы это было что-то с эффектом:

SELECT q.* from quota q
INNER JOIN latest_quota lq
ON lq.quota_unique_id=q.unique_id
WHERE q.percentage >= 95;

Это занимает 0,01 секунды с моими текущими данными, а не 5 минут или около того, требуется DataMapper для выполнения своего запроса. Есть ли способ заставить его делать то, что я хочу? У меня неправильные отношения? Я неправильно спрашиваю?

1 Ответ

6 голосов
/ 16 июля 2011

По какой-то причине вложенные запросы в стиле Hash всегда будут выполнять подвыборы.Для принудительного ВНУТРЕННЕГО СОЕДИНЕНИЯ используйте строковые пути запроса: LatestQuota.all ('quota.percentage.gte' => threshold)

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