使用JOIN的映射表比同一个表中的多个字段更好?

时间:2011-02-09 07:01:27

标签: mysql performance query-optimization

我有一张大约360,000条记录的表格,这里正在对两个索引字段执行查询:

SELECT COUNT(*)
FROM emails
WHERE
department_id IN(1,2,3,4)
AND category_id IN (5,6,7,8)

(Time: 0.9624802)

           id: 1
  select_type: SIMPLE
        table: emails
         type: range
possible_keys: emails_department_id_idx,emails_category_id_idx
          key: emails_category_id_idx
      key_len: 5
          ref: NULL
         rows: 54018
        Extra: Using where

因此那里只使用了一个索引。 (当使用更简单的比较或范围标准时,我可以使索引合并工作,但我需要对ID列表进行这样的检查。)

这里我创建了两个新表来映射这种关系,并使用JOIN我复制了相同的结果:

SELECT COUNT(*)
FROM emails
LEFT JOIN email_to_department ON (email_to_department.email_id = emails.id AND email_to_department.department_id IN (1,2,3,4))
LEFT JOIN email_to_category ON (email_to_category.email_id = emails.id AND email_to_category.category_id IN (5,6,7,8))
WHERE
email_to_department.department_id IS NOT NULL
AND email_to_category.category_id IS NOT NULL

(Time: 0.5217777)

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: email_to_category
         type: range
possible_keys: PRIMARY,category_id
          key: category_id
      key_len: 4
      ref: NULL
     rows: 61282
    Extra: Using where; Using index
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: email_to_department
         type: ref
possible_keys: PRIMARY,department_id
          key: PRIMARY
      key_len: 4
          ref: testdb.email_to_category.email_id
         rows: 1
        Extra: Using where; Using index
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: emails
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: testdb.email_to_category.email_id
         rows: 1
        Extra: Using index
3 rows in set (0.38 sec)

因此每个查询现在都使用一个索引,并且几乎减少了一半的时间。这是不好的设计吗?我应该以同样的方式写下其余的这些关系吗?

如果我以相同的方式添加更多条件,则查询的JOIN版本似乎变得更快,而另一个版本或多或少保持不变。

当然,对一个索引字段进行简单查询非常快:

SELECT COUNT(*)
FROM emails
WHERE department_id IN(1,2,3,4)

我可能会使用另一种策略来更快地进行这类查询吗?还有其他属性需要过滤,并且采用不同的组合,因此创建多列索引并不会有所帮助。

2 个答案:

答案 0 :(得分:1)

这实际上是关于数据库规范化的问题。您可以在许多地方查找有关该主题的信息。

基本答案由于有大量关于此的文献,并且存在很多差异,我只想指出它归结为权衡;速度与存储要求,或易用性与数据复制。您可能想了解规范化是什么,以便了解您为什么或不想这样做。

进一步阅读这是一个很深刻的话题,你可能想了解更多 - 有关这些问题的数百本书和数千篇学术论文。例如,看看之前关于设计数据库的SO问题: Database design: one huge table or separate tables?或此一个:First-time database design: am I overengineering? 或在About.com上Database Normalization Basics

答案 1 :(得分:0)

我也同意Jaitsu关于在这两个领域创建复合键。通常,您应始终将具有较高基数的列放在复合索引中。这样你就可以拥有更具选择性的索引。