如何减少规范化数据库中的查询数量?

时间:2011-11-25 13:51:25

标签: php mysql database relational-database normalization

想象一下文章的表格。除了主查询:

SELECT * From articles WHERE article_id='$id'

我们还需要其他几个查询来获取

SELECT * FROM users WHERE user_id='$author_id' // Taken from main query

SELECT tags.tag 
FROM tags 
  INNER JOIN tag_map 
    ON tags.tag_id=tag_map.tag_id 
WHERE article_id='$id'

以及针对类别,类似文章等的更多查询

问题1:这是使用PHP单独执行这些查询并处理给定结果的最佳方式,还是有办法将它们组合在一起?

问题2:在没有many-to-many关系的情况下(例如,tag_id,category_id,author_id标识的每篇文章的一个标签,类别,作者);从表中检索数据的最佳(最快)是什么。

3 个答案:

答案 0 :(得分:3)

如果所有关系都是一对多,那么您可以在一个查询中轻松检索所有这些数据,例如

SELECT
    [fields required]
FROM
    articles a
    INNER JOIN
        users u ON a.author_id=u.user_id
    INNER JOIN 
        tag_map tm ON tm.article_id=a.article_id
    INNER JOIN
        tags t t.tag_id=tm.tag_id
WHERE
    a.article_id='$id'

这通常比单独的三个查询快,因为你的表被正确编入索引,因为MySQL是为了这个而构建的!它可以节省两次到数据库的往返和相关的开销。

答案 1 :(得分:1)

您可以在第一个查询中合并用户:

SELECT a.*, u.*
FROM   articles a
JOIN   users u ON u.user_id = a.author_id
WHERE  a.article_id='$id';

可以对标签做同样的事情,但这会在答案中引入一些冗余,因为每篇文章显然有多个标签。可能或可能没有益处。

在没有many-to-many关系的情况下,这将一举完成工作,并且在任何情况下都会优越:

SELECT *
FROM   users u
JOIN   articles a ON a.author_id = u.user_id
JOIN   tag t      USING (tag_id)  -- I assume a column articles.tag_id in this case
WHERE  a.article_id = '$id';

您可能希望更具选择性在哪些列上返回。如果不保证标签存在,请将第二个JOIN设为LEFT JOIN

答案 2 :(得分:0)

您可以在规范化表格中添加适当的非规范化视图,其中每条记录都包含您需要的所有数据。或者,您可以将SQL调用封装在存储过程中,并从代码中调用这些proc,这有助于提高性能。证明两者并得到硬数据;总是更好地根据证据而不是想法做出决定。 :)