【发布时间】:2017-11-12 04:37:03
【问题描述】:
这是我的表结构:
// 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 标签)。我可以通过两种方式做到这一点:
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
看到了吗?第二种方法使用两个JOINs。我想它会比在庞大的数据集中使用REGEXP 慢。
你怎么看?我的意思是你的建议是什么,为什么?
【问题讨论】:
-
一个简单的。不可以。在 MySQL 中,函数不能使用索引。此外,这确实是对 GROUP BY 子句的滥用——尽管令人沮丧的是,它比正确的 DISTINCT 更快
-
第一个查询可能看起来更快,但实际上它会慢得多,因为使用
REGEXPMySQL 必须将keyword列中的每个值与正则表达式进行比较。keyword上的任何索引都将被忽略,整个posts表将被扫描。随着posts表变大,查询会变慢。 -
你猜。所以呢?我的建议是您阅读有关编程中的抽象和优化的内容,尤其是 SQL/DBMS。 PS你是什么意思,“规范化设计”?这里没有规范化设计,只是在非规范化设计中使用(显式)连接的第二个查询。
标签: mysql sql performance join