为了减少诸如COUNT和AVG之类的聚合函数(计算)的使用而进行非规范化:值得吗?

问题描述 投票:1回答:1

我正在尝试对列表查询进行一些优化。其中一些具有4个以上的联接(某些OUTER JOIN),需要使用GROUP BY的聚合函数(COUNT,AVG),有时还需要根据这些计算出的值进行排序。我看到同时使用了“临时”和“文件排序”。

我确实具有用于初始查询的缓存,但是我不打算缓存“更多加载”的缓存。我担心这些查询可能无法很好地扩展。

现在,我很想通过将计算出的值添加到主表中来进行非规范化。

假设我们目前已规范化:

SELECT p.id, p.product_name, p.time_created, COALESCE(AVG(r.rating),0) AS rating, COUNT(r.rating) AS review_count
FROM product AS p LEFT JOIN review AS r ON p.id = r.product_id 
GROUP BY p.id HAVING (rating, time_created) < (?, ?)
ORDER BY rating DESC, time_created DESC
LIMIT ?

非正规化,可能是:

SELECT id, product_name, time_created, rating, review_count
FROM product WHERE (rating, time_created) < (?, ?)
ORDER BY rating DESC, time_created DESC
LIMIT ?

在两个字段上都有索引。

归一化的阅读肯定更快。但是写起来肯定慢一些。我的问题是:这值得吗?

如果我这样做,应该吗?>

  1. 添加存储过程以在插入数据时计算冗余字段,
  2. 添加预定事件以进行计算,或
  3. 仅让程序进行计算,因为速度并不重要(尽管DB上的负载可能会如此)?
  4. 编辑:

我实现了它,并在源代码上添加了一些触发器,以在每次更改视图时计算视图。读取速度可能会快40%(使用50行测试数据,由于未使用“临时”表,希望可以更好地扩展)。这可能是实现它的最简单方法。插入速度较慢。我保留两个版本,并会监视真实数据。

我添加的触发器之一是这样的:

CREATE TRIGGER review_insert AFTER INSERT ON product_review FOR EACH ROW
UPDATE product AS p
SET p.rating = 
(SELECT COALESCE(AVG(r.rating),0) FROM product_review AS r WHERE r.product_id = p.id);

我正在尝试对列表查询进行一些优化。它们中的一些具有4个以上的联接(某些OUTER JOIN),需要使用GROUP BY的聚合函数(COUNT,AVG),有时还需要按...

mysql sql group-by aggregate-functions denormalization
1个回答
1
投票

此评论太长了。

© www.soinside.com 2019 - 2024. All rights reserved.