Таблица соединений Rails делает плохой sql - PullRequest
2 голосов
/ 27 марта 2009

ОБНОВЛЕНО: для включения модельных отношений

У меня есть таблица со многими ко многим группам и событиям (у события много групп, у группы много событий ...)

У меня есть главная страница, на которой перечислены все события, и недавняя страница, на которой отображаются события, обновленные за последние 7 дней.

Может кто-нибудь объяснить, почему недавний метод генерирует совершенный sql со всеми включенными объединениями

@events = Event.find(:all, :include => [:venue, :bands], :conditions => {:updated_at => d1..DateTime.now}, :order => 'events.updated_at desc')

И метод main генерирует ужасный sql, который запрашивает таблицу диапазонов для каждого события.

@events = Event.find(:all, :include => [:venue, :bands], :order => 'events.day')

Они оба используют одно и то же представление, больше никакой обработки / запросов не происходит. Единственное различие между ними заключается в параметре: condition и столбце, по которому производится сортировка. Это сводит меня с ума!

Извините, вот мои модели и их отношения

event.rb

has_many :event_bands
has_many :bands, :through => :event_bands
belongs_to :venue

band.rb

has_many :event_bands
has_many :events, :through => :event_bands

event_bands.rb

belongs_to :event
belongs_to :band

sql, сгенерированный недавно:

Processing EventlistController#recent (for 127.0.0.1 at 2009-03-27 14:58:10) [GET]
  [4;35;1mSQL (0.0ms)[0m   [0mSET SQL_AUTO_IS_NULL=0[0m
  [4;36;1mEvent Columns (16.0ms)[0m   [0;1mSHOW FIELDS FROM `events`[0m
  [4;35;1mVenue Columns (15.0ms)[0m   [0mSHOW FIELDS FROM `venues`[0m
  [4;36;1mBand Columns (16.0ms)[0m   [0;1mSHOW FIELDS FROM `bands`[0m
  [4;35;1mEvent Load Including Associations (31.0ms)[0m   [0mSELECT `events`.`id` AS t0_r0, `events`.`is_local` AS t0_r1, `events`.`link` AS t0_r2, `events`.`notes` AS t0_r3, `events`.`band_id` AS t0_r4, `events`.`venue_id` AS t0_r5, `events`.`created_at` AS t0_r6, `events`.`updated_at` AS t0_r7, `events`.`day` AS t0_r8, `events`.`band_list` AS t0_r9, `venues`.`id` AS t1_r0, `venues`.`name` AS t1_r1, `venues`.`link` AS t1_r2, `venues`.`map` AS t1_r3, `venues`.`notes` AS t1_r4, `venues`.`created_at` AS t1_r5, `venues`.`updated_at` AS t1_r6, `bands`.`id` AS t2_r0, `bands`.`name` AS t2_r1, `bands`.`link` AS t2_r2, `bands`.`notes` AS t2_r3, `bands`.`is_local` AS t2_r4, `bands`.`created_at` AS t2_r5, `bands`.`updated_at` AS t2_r6 FROM `events` LEFT OUTER JOIN `venues` ON `venues`.id = `events`.venue_id LEFT OUTER JOIN `event_bands` ON (`events`.`id` = `event_bands`.`event_id`) LEFT OUTER JOIN `bands` ON (`bands`.`id` = `event_bands`.`band_id`) WHERE (`events`.`updated_at` BETWEEN '2009-03-20 14:58:10' AND '2009-03-27 14:58:10')

sql, сгенерированный main

Processing EventlistController#index (for 127.0.0.1 at 2009-03-27 14:15:47) [GET]
  [4;35;1mSQL (0.0ms)[0m   [0mSET SQL_AUTO_IS_NULL=0[0m
  [4;36;1mEvent Load (0.0ms)[0m   [0;1mSELECT * FROM `events` ORDER BY events.day[0m
  [4;35;1mEvent Columns (15.0ms)[0m   [0mSHOW FIELDS FROM `events`[0m
  [4;36;1mVenue Columns (16.0ms)[0m   [0;1mSHOW FIELDS FROM `venues`[0m
  [4;35;1mVenue Load (0.0ms)[0m   [0mSELECT * FROM `venues` WHERE (`venues`.`id` IN (6,7,8,9,1,2,3,4,5)) [0m
  [4;36;1mEventBand Load (0.0ms)[0m   [0;1mSELECT `event_bands`.* FROM `event_bands` WHERE (`event_bands`.event_id IN (1,24,74,2,75,11,12,3,13,129,76,14,77,78,145,4,146,120,15,130,79,147,5,80,148,144,131,81,132,16,28,82,121,133,83,17,134,84,149,6,18,135,85,122,19,7,136,86,20,9,87,25,137,150,22,138,88,151,124,123,139,89,152,140,90,141,91,8,153,21,142,154,125,143,92,126,10,93,94,155,127,95,128,23,96,97,26,98,99,27,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119)) [0m
  [4;35;1mEventBand Columns (0.0ms)[0m   [0mSHOW FIELDS FROM `event_bands`[0m
  [4;36;1mBand Columns (16.0ms)[0m   [0;1mSHOW FIELDS FROM `bands`[0m
  [4;35;1mBand Load (0.0ms)[0m   [0mSELECT * FROM `bands` WHERE (`bands`.`

1 Ответ

3 голосов
/ 28 марта 2009

Причина, по которой они генерируют два разных запроса SQL, заключается в том, что Rails по умолчанию пытается оптимизировать ваши запросы SQL для меньшего количества соединений. Когда вы включаете список условий как часть вашей находки, которые требуют использования других таблиц, тогда, конечно, результирующий SQL должен включать соединение. Но если все, что вы просите, это предварительно заполнить объекты связями с объектами, которые вы извлекаете, то Rails считает, что более эффективно выполнять несколько быстрых запросов, а не один большой медленный запрос.

Обратите внимание, что это не вызывает проблемы N + 1, потому что Rails попытается загрузить все связанные записи в одном запросе.

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