想象一下这个场景:
我的数据库中有三个表:产品、用户和喜欢,后者表示产品<之间的关系/em> 和一个用户。现在我有一个查询,它将 Products 与 Likes 表连接起来,计算 Product 获得了多少个 Likes。
事实上,我比实际用户更频繁地需要有关计数的信息,并且我希望将上面的查询用作 View 中更大查询的一部分。是否可以优化查询或 View ,以便 MySQL 以某种方式缓存上面计数查询的结果?
最佳答案
我不知道有什么方法可以用 mysql 做到这一点(但我主要使用 postgres,所以这可能是可能的,但我只是不知道)。我建议两个选择:
- 如果您需要缓存尽可能保持最新,请添加
likes_count
专栏到您的Products
表,创建AFTER INSERT
和AFTER DELETE
在Likes
上触发表(假设您从未更新该表),当将新行插入Likes
时,该表会增加产品的相似计数表并在删除行时减少它。然后,添加一个执行UPDATE Products SET likes_count=(SELECT COUNT(1) FROM Likes WHERE product_id = Products.id)
的 cronjob偶尔要确保这些值确实是最新的 - 使用触发器维护计数永远不会 100% 准确。 - 另一个选项是创建一个 View
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这会将缓存表与 View 中的最新信息同步。那么,如果您需要准确的结果,您可以直接从 View 中获取数据。否则,使用缓存表。
如果你选择第一个选项,触发器应该看起来像这样(我的 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;
关于mysql - 如何有效地聚合 View 中的相关对象计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7087029/