慢加入? NULL ref哪个更好

时间:2011-04-02 00:53:40

标签: mysql join

我有两张桌子:

CREATE TABLE `bb_index` (
  `bb_id` smallint(5) unsigned NOT NULL,
  `object_id` bigint(10) unsigned NOT NULL,
  `in_object_id` bigint(10) unsigned NOT NULL,
  `f` int(10) unsigned DEFAULT NULL,
  `length` decimal(10,5) DEFAULT NULL,
  PRIMARY KEY (`bb_id`,`object_id`,`in_object_id`),
  KEY `in_obj_key` (`bb_id`,`in_object_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


CREATE TABLE `obj_bb_relation` (`bb_id` smallint(5) unsigned NOT NULL DEFAULT '0',
  `object_id` bigint(10) unsigned NOT NULL DEFAULT '0',
  `object_bb_f` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`bb_id`,`object_id`),
  KEY `object_id` (`object_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

哪个更好: 选项1:

SELECT object_id, f, length , object_bb_freq as C 
  FROM (select object_id, f, length 
          from bb_index use index (in_obj_key) 
         where bb_id = 14 
           and in_object_id = XXX
       ) as a join obj_bb_relation as b using (object_id)

说明:

enter image description here

选项2:

SELECT object_id, f, length, object_bb_f AS C 
  FROM bb_index AS a 
  JOIN obj_bb_relation AS b USING ( object_id ) 
 WHERE in_object_id = XXX 
   AND a.bb_id =YY 
   AND b.bb_id =YY 

enter image description here

OR?

另一种选择..?

2 个答案:

答案 0 :(得分:0)

在大多数情况下两者都是相同的。大多数数据库系统现在都有查询优化,它会自动从查询2,查询1进行查询。甚至更好。但是如果你使用一些非常旧的或简化的数据库,选项1会更好。除了一些非常特殊的情况,加入应该是最后的。

答案 1 :(得分:0)

首先,您的查询几乎不相似!

SELECT object_id, f, length , object_bb_freq as C
FROM (select object_id, f, length
      from bb_index use index (in_obj_key)
      where bb_id = 14 and in_object_id = XXX) as a
join obj_bb_relation as b
     using (object_id)

SELECT object_id, f, length, object_bb_f AS C
FROM bb_index AS a
JOIN obj_bb_relation AS b
     USING ( object_id )
WHERE in_object_id = XXX AND a.bb_id =YY AND b.bb_id =YY 

翻译中缺少非常重要的位,即

  • bb_index上的强制索引
  • b.bb_id上的过滤器

除此之外,因为您使用了ANSI INNER JOIN表单而不是逗号形式(FROM bb_index, obj_bb_relation WHERE ..),所以MySQL会根据需要随机播放WHERE和ON / USING子句,因为它们是在语义上是一样的。这与你已经subqueried a的事实无关,因为MySQL非常聪明,可以展开它。

就个人而言,由于你在a.bb_id和b.bb_id上都有过滤器,如果你知道一个表只返回另一个表的1%的记录,那么你可以使用经常被诽谤的逗号。表示法(FROM bb_index, obj_bb_relation WHERE ..)因为MySQL会在加入bb_index之前处理obj_bb_relation上的过滤器 - 否则我通常会使用展平的JOIN表单(选项2),因为它比子查询更清晰在选项1)