【问题标题】:Rails join table renders bad sqlRails 连接表呈现错误的 sql
【发布时间】:2009-03-27 19:13:19
【问题描述】:

更新:包括模型关系

我在乐队和活动之间有一个多对多连接表(一个活动有很多乐队,一个乐队有很多活动......)

我有一个列出所有事件的主页,以及一个显示过去 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')

它们都使用相同的视图,没有其他处理/查询正在进行。两者之间的唯一区别是 :conditions 参数及其排序所在的列。这快把我逼疯了!

抱歉,这是我的模型及其关系

事件.rb

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

乐队.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')

main生成的sql

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`.`

【问题讨论】:

  • 如果取出:conditions,第一个生成什么sql?这至少会告诉你它是由于 :conditions 还是由于 :order。
  • 更好的是,贴出两个例子生成的sql。另外,您使用的是哪个版本的 Rails,因为这是最近几个月一直在变化的领域。
  • 这不是:order,如果我把它拿出来,sql 保持不变。我正在使用 rails 2.2.2

标签: mysql ruby-on-rails activerecord


【解决方案1】:

它们生成两个不同的 SQL 查询的原因是 Rails 默认尝试优化您的 SQL 查询以减少连接。当您将条件列表作为查找的一部分包含在需要使用其他表的部分时,那么生成的 SQL 当然必须包含连接。但是,如果您要求做的只是预先填充与您正在检索的对象的关系的对象,那么 Rails 认为执行几个快速查询而不是一个大的慢查询更有效。

请注意,这不会导致 N+1 问题,因为 Rails 会尝试在单个查询中加载所有关联的记录。

【讨论】:

  • 谢谢,这是有道理的。所以你的建议是让 ActiveRecords 做它的事?
  • 可能,是的。如果需要,请务必编写自定义 SQL; ActiveRecord 不能解决世界上所有的问题。但在这种特殊情况下,事实上,这种疯狂是有原因的。
  • 自然而然。我只是对这个简单连接的结果感到非常困惑。谢谢!
猜你喜欢
  • 2020-07-21
  • 1970-01-01
  • 2016-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多