使用联接映射表是否比在同一张表中使用多个字段更好?
使用联接映射表是否比在同一张表中使用多个字段更好?
我有一个大约有36万条记录的表,这里执行了一个查询,查询了两个有索引的字段:
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)
是否有其他策略可以让这些查询更快?还有其他需要进行过滤的属性,并且以不同的组合方式进行过滤,因此创建多列索引并不能真正帮助解决问题。
这实际上是一个关于数据库规范化的问题。您可以在许多地方查找有关该主题的信息。
基本答案由于这方面有大量的文献和许多差异,我只想指出,这归结为权衡;速度与存储要求之间的权衡,或者易用性与数据重复之间的权衡。为了了解为什么应该或不应该这样做,您可能希望了解规范化是什么。
进一步阅读这是一个深入的话题,您可能希望学习更多-这些问题有数百本书和数千篇学术论文。例如,看看关于设计数据库的这个之前的SO问题:Database design: one huge table or separate tables?,或者这一个:First-time database design: am I overengineering?,或者关于数据库规范化基础知识的这个:Database Normalization Basics
在About.com上。
问题的出现原因是关于数据库规范化的问题。数据库规范化是一种将数据库设计为更高效和可维护的方式的方法。它有助于减少数据冗余,提高查询性能,并使数据更容易管理和更新。
解决方法是使用连接映射表而不是在同一张表中使用多个字段。连接映射表是将多对多关系表示为两个单独的表,并使用外键将它们连接起来的一种方法。这样可以避免数据冗余,并且在查询时可以更高效地进行连接操作。
通过使用连接映射表,可以更好地组织和管理数据,提高查询性能,并减少数据冗余。这种方法可能需要更多的存储空间,但可以提供更好的灵活性和可扩展性。
总之,使用连接映射表比在同一表中使用多个字段更好,因为它可以提高数据库的规范化程度,减少数据冗余,并提高查询性能。这是一个常见的数据库设计原则,可以在数据库规范化的文献和资源中找到更多详细信息。
在这个问题中,我们讨论了在数据库中使用JOIN连接的映射表是否比在同一张表中使用多个字段更好的原因和解决方法。
通常情况下,我们会将具有较高基数的列放在复合索引的第一位,这样可以创建一个更具选择性的索引。这种做法可以提高查询的性能,并且可以更好地优化查询计划。
在数据库设计中,使用JOIN连接的映射表可以提供更好的可扩展性和灵活性。如果我们在同一张表中使用多个字段来存储数据,可能会导致表结构变得复杂,难以维护和查询。
使用JOIN连接的映射表可以更好地组织和管理数据。通过将相关的数据分散到不同的表中,我们可以更容易地进行数据查询和分析。此外,使用JOIN连接的映射表还可以减少数据冗余,并提高数据的一致性和完整性。
解决这个问题的方法是创建一个复合索引,将具有较高基数的列放在第一位。这样可以创建一个更具选择性的索引,提高查询的性能。此外,我们还可以使用JOIN连接的映射表来更好地组织和管理数据,提高数据的一致性和完整性。通过将相关的数据分散到不同的表中,我们可以更容易地进行数据查询和分析。
下面是一个示例,展示了如何使用JOIN连接的映射表来解决这个问题:
-- 创建映射表
CREATE TABLE table1 (
id INT PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE table2 (
id INT PRIMARY KEY,
table1_id INT,
FOREIGN KEY (table1_id) REFERENCES table1(id),
attribute VARCHAR(50)
);
-- 创建复合索引
CREATE INDEX idx_table2 ON table2 (table1_id, attribute);
通过使用JOIN连接的映射表,我们可以更好地组织和管理数据,并提高查询的性能。这种方法可以在数据库设计和查询优化中发挥重要作用。