使用 JOIN'ed 映射表比同一张表中的多个字段更好?
Posted
技术标签:
【中文标题】使用 JOIN\'ed 映射表比同一张表中的多个字段更好?【英文标题】:Using JOIN'ed mapping tables better than multiple fields in the same table?使用 JOIN'ed 映射表比同一张表中的多个字段更好? 【发布时间】:2011-06-23 22:50:39 【问题描述】:我有一个包含大约 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)
我是否可以使用另一种策略来加快这类查询的速度?还有其他属性需要过滤,并且需要以不同的组合进行过滤,因此创建多列索引并没有真正的帮助。
【问题讨论】:
在您的第一个查询中,您可能希望考虑在 department_id 和 category_id 上添加一个键,如下所示,INDEX(department_id, category_id)。这将有助于使用索引的第一个查询过滤结果。 【参考方案1】:这确实是一个关于数据库规范化的问题。您可以在许多地方查找有关该主题的信息。
基本答案 由于这方面的文献很多,而且存在很多差异,我只想指出它归结为权衡;速度与存储要求,或易用性与数据复制。您可能想了解什么是标准化,以便了解您为什么愿意或不愿意这样做。
进一步阅读 这是一个深奥的话题,您可能想了解更多信息 - 关于这些问题有数百本书和数千篇学术论文。例如,看看这个关于设计数据库的先前 SO 问题: Database design: one huge table or separate tables?,或者这个:First-time database design: am I overengineering? 或 Database Normalization Basics About.com。
【讨论】:
【参考方案2】:我也同意 Jaitsu 关于在两个字段上创建复合键的观点。通常,您应该始终将具有较高基数的列放在复合索引的最前面。这样您就可以拥有更具选择性的索引。
【讨论】:
以上是关于使用 JOIN'ed 映射表比同一张表中的多个字段更好?的主要内容,如果未能解决你的问题,请参考以下文章
想写一个DB2触发器,几张表有关联,修改其中一张主表中的某一个字段,其他关联表中的该字段也跟着联动修改