当有多个JOINS时,是否更好地使用非标准化设计?

时间:2017-06-10 05:44:37

标签: mysql sql performance join

这是我的表结构:

// posts
+----+-----------+---------------------+-------------+
| id |   title   |        body         |   keywords  |
+----+-----------+---------------------+-------------+
| 1  | title1    | Something here      | php,oop     |
| 2  | title2    | Something else      | html,css,js |
+----+-----------+---------------------+-------------+

// tags
+----+----------+
| id |   name   |
+----+----------+
| 1  | php      |
| 2  | oop      |
| 3  | html     |
| 4  | css      |
| 5  | js       |
+----+----------+

// pivot
+---------+--------+
| post_id | tag_id |
+---------+--------+
| 1       | 1      |
| 1       | 2      |
| 2       | 3      |
| 2       | 4      |
| 2       | 5      |
+---------+--------+

如您所见,我以两种方式存储关键字。两者都作为字符串放入名为keywords的列中,并作为与其他表的关系。

现在我需要选择所有包含特定关键字的帖子(例如phphtml标签)。我可以通过两种方式做到这一点:

1:使用非标准化设计:

SELECT * FROM posts WHERE keywords REGEXP 'php|html';

2:使用规范化设计:

SELECT     posts.id, posts.title, posts.body, posts.keywords 
FROM       posts
INNER JOIN pivot ON pivot.post_id = posts.id
INNER JOIN tags ON tags.id = pivot.tag_id
WHERE      tags.name IN ('html', 'php')
GROUP BY   posts.id

请参阅?第二种方法使用两个JOIN。我想它会比在庞大的数据集中使用REGEXP慢。

你怎么看?我的意思是你的建议是什么以及为什么?

3 个答案:

答案 0 :(得分:0)

在小表格中,您可以自行决定使用两者。

如果你希望桌子增长,你真的需要第二选择。背后的原因是正则表达式永远不能在 MySQL 中使用索引索引是快速查询的关键。 如果在列上声明索引, join 将使用索引;

答案 1 :(得分:0)

  

第二种方法使用两个JOIN。我猜它会慢一些   在庞大的数据集中使用REGEXP。

你的直觉是完全错误的。数据库旨在执行JOIN。他们可以利用索引和分区来加速查询。更高级的数据库(比MySQL)使用表的统计信息来选择执行查询的最佳算法。

您的第一个查询始终需要posts的全表扫描。您的第二个查询可以通过各种方式进行优化。

此外,使用第一种方法,保持数据中数据的一致性要困难得多。您可能需要实现触发器来处理所有表上的更新和插入。这会让事情变慢。

在某些情况下,值得努力做到这一点 - 考虑汇总计数或美元或时间总计。将标记放入分隔的字符串中的可能性要小得多,因为在SQL中解析字符串相对于其他成本来说可能不是一个非常大的好处。

答案 2 :(得分:0)

当我们谈论较低规模的数据时,所有这些看起来都很好。 OLTP系统具有非规范化表是非常基础的理论。当您希望您的表可以扩展并希望数据非冗余且一致时,标准化就是答案。当然,加入涉及成本,但这些都是微不足道的。

让我们谈谈你的情景:

    优点:

  • 查询一个表格的所有可用数据。


    缺点:

  • 跨列包装的函数强制查询优化器扫描整个表,而不管列索引如何。从数据扩展的角度来看,这非常重要。
  • 您案例中的关键字会重复多次导致数据冗余。
  • 关键字多次出现会导致数据不一致,如果要删除/更新关键字,则需要搜索列并替换每行的所有位置。如果任何关键字留在任何地方,都会导致数据完整性问题。

还有更多。在RDBMS中进行数据规范化