如何有效地聚合视图中的相关对象计数?

时间:2011-08-17 01:28:13

标签: mysql sql query-optimization

想象一下这种情况:

我的数据库中有三个表:产品用户喜欢,后者表示产品<之间的关系/ em>和用户。现在我有一个查询,它将产品 Likes 表连接起来,计算产品获得的数量。

事实上,我比实际用户更频繁地需要关于计数的信息,并且我想在视图中使用上面的查询作为更大查询的一部分。是否可以优化查询或视图,以便MySQL以某种方式缓存上面的计数查询的结果?

2 个答案:

答案 0 :(得分:1)

我不知道用mysql做这个的方法(但我主要使用postgres,所以它可能是我可能不知道的)。我建议两个选择:

  • 如果您需要尽可能更新缓存,请在likes_count表格中添加Products列,然后创建AFTER INSERTAFTER DELETE个触发器Likes表(假设您永远不会更新该表),当新行插入Likes表时会增加产品的相似数,并在删除行时减少它。然后,添加一个偶尔执行UPDATE Products SET likes_count=(SELECT COUNT(1) FROM Likes WHERE product_id = Products.id)的cronjob,以确保这些值真正是最新的 - 使用触发器维持计数绝不是100%准确。
  • 另一个选项是创建一个视图CREATE VIEW Products_Likes_View AS SELECT product_id, COUNT(*) AS likes_count FROM Likes GROUP BY product_id;,并创建一个缓存表,如CREATE TABLE Products_Likes_Cache (product_id INTEGER PRIMARY KEY, likes_count INTEGER NOT NULL);。然后,添加一个执行BEGIN; TRUNCATE Products_Likes_Cache; INSERT INTO Products_Likes_Cache SELECT * FROM Products_Likes_View; COMMIT;的cronjob,它将使缓存表与视图中的最新信息同步。如果您需要准确的结果,则可以直接从视图中获取数据。否则,请使用缓存表。

如果你使用第一个选项,触发器应该看起来像这样(我的MySQL技能有点生疏,我可能会使用确切的语法):

CREATE TRIGGER product_increase_likes AFTER INSERT ON Likes
    FOR EACH ROW BEGIN
        UPDATE Products SET likes_count=likes_count+1 WHERE id=NEW.product_id
    END;

CREATE TRIGGER product_decrease_likes AFTER DELETE ON Likes
    FOR EACH ROW BEGIN
        UPDATE Products SET likes_count=likes_count-1 WHERE id=OLD.product_id
    END;

答案 1 :(得分:1)

您不应该需要联接来计算产品的喜好。

SELECT product, count(*) 
FROM likes
GROUP BY product;

如果使用WHERE子句,应该快速翻录。