Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql Isn';当存在多个联接时,是否可以更好地使用非规范化设计?_Mysql_Sql_Performance_Join - Fatal编程技术网

Mysql Isn';当存在多个联接时,是否可以更好地使用非规范化设计?

Mysql Isn';当存在多个联接时,是否可以更好地使用非规范化设计?,mysql,sql,performance,join,Mysql,Sql,Performance,Join,以下是我的表格结构: // posts +----+-----------+---------------------+-------------+ | id | title | body | keywords | +----+-----------+---------------------+-------------+ | 1 | title1 | Something here | php,oop | | 2 | tit

以下是我的表格结构:

// 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      |
+---------+--------+
如您所见,我以两种方式存储关键字。既可以作为字符串输入到名为
关键字的列中,也可以作为关系输入到其他表中


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

1:使用非规范化设计: 2:使用规范化设计:
看到了吗?第二种方法使用两个
JOIN
s。我想它比在庞大的数据集中使用
REGEXP
要慢


你觉得怎么样?我的意思是你的建议是什么?为什么?

在小表格中,你可以根据自己的判断使用这两种方法

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

在小表格中,您可以自行决定使用这两种方法

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

第二种方法使用两个连接。我想它会比以前慢 在大型数据集中使用REGEXP

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

您的第一个查询总是需要对
posts
进行完整的表扫描。您的第二个查询可以通过各种方式进行优化

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

在某些情况下,这样做是值得的——想想汇总计数或美元或时间的总数。将标记放入带分隔符的字符串中的好处要小得多,因为在SQL中解析字符串相对于其他成本来说不太可能是一个真正大的好处

第二种方法使用两个连接。我想它会比以前慢 在大型数据集中使用REGEXP

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

您的第一个查询总是需要对
posts
进行完整的表扫描。您的第二个查询可以通过各种方式进行优化

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


在某些情况下,这样做是值得的——想想汇总计数或美元或时间的总数。将标记放入带分隔符的字符串中的好处要小得多,因为与其他成本相比,在SQL中解析字符串不太可能是一个真正大的好处。

当我们以较低的规模谈论数据时,所有这些都看起来不错。对OLTP系统来说,表的非规范化是非常基本的理论。当您希望表能够扩展并希望数据不冗余且一致时,标准化就是答案。当然,join需要付出代价,但这对于所有这些问题来说都是微不足道的。

让我们谈谈您的场景:

优点:

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

缺点:

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

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

当我们谈论低规模的数据时,所有这些看起来都很好。对OLTP系统来说,表的非规范化是非常基本的理论。当您希望表能够扩展并希望数据不冗余且一致时,标准化就是答案。当然,join需要付出代价,但这对于所有这些问题来说都是微不足道的。

让我们谈谈您的场景:

优点:

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

缺点:

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

还有很多。在RDBMS中进行数据标准化。

一个简单的标准化。不可以。在MySQL中,函数不能使用索引。此外,这实际上是对GROUP BY子句的滥用-尽管令人沮丧的是,它比正确的对应语句快。第一个查询可能看起来快,但实际上它将比
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