简体   繁体   English

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

[英]How to reduce the number of queries in a normalized database?

Imagine a table for articles. 想象一下一张摆有物品的桌子。 In addition to the main query: 除了主要查询:

SELECT * From articles WHERE article_id='$id'

We also need several other queries to get 我们还需要其他几个查询来获取

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'

and several more queries for categories, similar articles, etc 以及更多关于类别,类似文章等的查询

Question 1: Is it the best way to perform these queries separately with PHP and handle the given results, or there is way to combine them? 问题1:是用PHP单独执行这些查询并处理给定结果的最佳方法,还是有将它们组合的最佳方法?

Question 2: In the absence of many-to-many relationships (eg one tag, category, author for every article identified by tag_id, category_id, author_id); 问题2:在没有many-to-many关系的情况下(例如,每个标签,类别,作者由tag_id,category_id,author_id标识的每篇文章); What the best (fastest) was to retrieve data from the tables. 最好(最快)的是从表中检索数据。

If all the relationships are one-many then you could quite easily retrieve all this data in one query such as 如果所有关系都是一对多的,那么您可以很容易地在一个查询中检索所有这些数据,例如

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'

This would usually be faster than the three queries separately along as your tables are indexed correctly as MySQL is built to do this! 通常,这比单独的三个查询要快,因为您的表已正确建立索引,因为MySQL是为此而建立的! It would save on two round trips to the database and the associated overhead. 这样可以节省两次往返数据库的时间以及相关的开销。

You can merge in the user in the first query: 您可以在第一个查询中合并用户:

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

You could do the same with the tags, but that would introduce some redundancy in the answer, because there are obviously multiple tags per article. 可以对标签进行相同的操作,但这会在答案中引入一些冗余,因为每篇文章显然有多个标签。 May or may not be beneficial. 可能会或可能不会有好处。

In the absence of many-to-many relationships, this would do the job in one fell swoop and would be superior in any case: 在没有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';

You may want to be more selective on which columns to return. 您可能希望对要返回的列更具选择性 If tags ar not guaranteed to exist, make the second JOIN a LEFT JOIN . 如果不能保证存在标签,则使第二个JOIN成为LEFT JOIN

You could add an appropriately denormalized view over your normalized tables where each record contains all the data you need. 您可以在规范化表上添加适当的非规范化视图,其中每个记录都包含所需的所有数据。 Or you could encapsulate the SQL calls in stored procedures and call these procs from your code, which should aid performance. 或者,您可以将SQL调用封装在存储过程中,然后从代码中调用这些proc,这应有助于提高性能。 Prove both out and get the hard figures; 证明并得到困难的数字; always better to make decisions based on evidence rather that ideas. 总是最好根据证据而不是想法来做出决定。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM