这是我的表结构:
// 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
的列中,并作为与其他表的关系。
现在我需要选择所有包含特定关键字的帖子(例如php
和html
标签)。我可以通过两种方式做到这一点:
SELECT * FROM posts WHERE keywords REGEXP 'php|html';
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
慢。
答案 0 :(得分:0)
在小表格中,您可以自行决定使用两者。
如果你希望桌子增长,你真的需要第二选择。背后的原因是正则表达式永远不能在 MySQL 中使用索引。 索引是快速查询的关键。 如果在列上声明索引, join 将使用索引;
答案 1 :(得分:0)
第二种方法使用两个JOIN。我猜它会慢一些 在庞大的数据集中使用REGEXP。
你的直觉是完全错误的。数据库旨在执行JOIN。他们可以利用索引和分区来加速查询。更高级的数据库(比MySQL)使用表的统计信息来选择执行查询的最佳算法。
您的第一个查询始终需要posts
的全表扫描。您的第二个查询可以通过各种方式进行优化。
此外,使用第一种方法,保持数据中数据的一致性要困难得多。您可能需要实现触发器来处理所有表上的更新和插入。这会让事情变慢。
在某些情况下,值得努力做到这一点 - 考虑汇总计数或美元或时间总计。将标记放入分隔的字符串中的可能性要小得多,因为在SQL中解析字符串相对于其他成本来说可能不是一个非常大的好处。
答案 2 :(得分:0)
当我们谈论较低规模的数据时,所有这些看起来都很好。 OLTP系统具有非规范化表是非常基础的理论。当您希望您的表可以扩展并希望数据非冗余且一致时,标准化就是答案。当然,加入涉及成本,但这些都是微不足道的。
让我们谈谈你的情景:
优点:
缺点:
还有更多。在RDBMS中进行数据规范化。