我有一个名为 rating 的表格,其中包含以下字段:
+-----------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+----------------+
| rating_id | bigint(20) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | MUL | NULL | |
| movie_id | int(11) | NO | | NULL | |
| rating | float | NO | | NULL | |
+-----------+------------+------+-----+---------+----------------+
此表中的索引:
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| ratings | 0 | PRIMARY | 1 | rating_id | A | 100076 | NULL | NULL | | BTREE | | |
| ratings | 0 | user_id | 1 | user_id | A | 564 | NULL | NULL | | BTREE | | |
| ratings | 0 | user_id | 2 | movie_id | A | 100092 | NULL | NULL | | BTREE | | |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
我有另一个名为movie_average_ratings
的表格,其中包含以下字段:
+----------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------+------+-----+---------+-------+
| movie_id | int(11) | NO | PRI | NULL | |
| average_rating | float | NO | | NULL | |
+----------------+---------+------+-----+---------+-------+
因为很明显,我想从评分表中计算电影的平均评分,并更新movie_average_ratings
表格。我尝试了以下SQL查询。
UPDATE movie_average_ratings
SET average_rating = (SELECT AVG(rating)
FROM ratings
WHERE ratings.movie_id = movie_average_ratings.movie_id);
目前,大约有10,000条电影记录和100,000条评级记录,我收到Lock wait timeout exceeded; try restarting transaction
错误。记录数量可能会显着增长,因此我认为增加超时不是一个好的解决方案。
那么,我如何编写'可伸缩'查询来实现这一目标呢?迭代movie_average_ratings
表记录并单独计算平均值是最有效的解决方案吗?
答案 0 :(得分:1)
如果没有explain
,就很难清楚是什么阻碍了你。通过将此聚合数据存储为非规范化表,您还不清楚是否会获得性能提升 - 如果计算评级的查询在0.04秒内执行,则不太可能查询非规范化表格会更快。
一般情况下,如果您知道您遇到了性能问题,我建议仅进行非规范化。
但这不是问题。
我会做以下事情:
delete from movie_average_ratings;
insert into movie_average_ratings
Select movie_ID, avg(rating)
from ratings
group by movie_id;
答案 1 :(得分:0)
我刚在另一个post找到了一些东西:
发生的事情是,其他一些线程正在进行记录锁定 一些记录(你正在更新表中的每条记录!)太久了, 并且你的线程正在超时。
这意味着您的某些记录已被锁定,您可以在控制台中强制解锁它们:
1)输入MySQL
@path\script.sql
2)让我们看一下锁定表
的列表mysql -u your_user -p
3)让我们看一下当前进程的列表,其中一个是锁定的 你的桌子
mysql> show open tables where in_use>0;
4)杀死其中一个进程
mysql> show processlist;
答案 2 :(得分:0)
您可以将movie_average_ratings表重新设计为
movie_id (int)
sum_of_ratings (int)
num_of_ratings (int)
然后,如果添加了新评级,您可以将其添加到movie_average_ratings并计算平均值(如果需要)