MySQL更新字段來自另一個表的count()值


假設有文章post和評論comment兩個表,文章表記錄有評論的數量,但是這個值我們要一次更新。

如下,現在post表的comment_count都是0,我們的目標是:執行一個SQL語句,讓其把統計comment表的數據數量。

post表數據如下:

+---------+-------------------+---------------+
| post_id | title             | comment_count | +---------+-------------------+---------------+ | 1 | How to lean MySQL | 0 | | 2 | How to lean PHP | 0 | | 3 | How to lean Redis | 0 | +---------+-------------------+---------------+

comment表數據如下:

+------------+---------+---------+
| comment_id | post_id | content | +------------+---------+---------+ | 1 | 1 | Good! | | 2 | 1 | Nice! | | 3 | 1 | Yeap! | +------------+---------+---------+

因為這里只有post_id=1的文章有評論,所以最終的comment_count值分別為:3 0 0

1 使用SQL語句

在數據量為100W以下的時候,可以用一條命令解決:

UPDATE post AS a SET comment_count = (select count(*) FROM comment WHERE post_id=a.post_id);

2 使用存儲過程(數據量巨大時用)

當數據量很大的時候,比如1億條記錄,如果再用上面這條命令,就會導致所有行被鎖定(InnoDB存儲引擎)。

UPDATE語句首先會查找需要更新的行,如果符合要求,先鎖定,然后再更新,

上面這條語句會鎖定所有行,等效於鎖定全表。

解決這個問題的辦法就是,按post表的post_id范圍批量更新,具體代碼如下:

DROP PROCEDURE IF EXISTS UpdateCount; DELIMITER // CREATE PROCEDURE UpdateCount() BEGIN DECLARE lower INT; # ID下限 DECLARE upper INT; # ID上限 DECLARE step INT; # 次增加步數 DECLARE max_id INT; # 最大ID SET lower = 1; SET upper = 0; SET step = 10000; # 每次更新1萬條數據 SET max_id = 0;  # 從庫中讀取最大ID SELECT max(post_id) INTO max_id FROM post; WHILE lower <= max_id DO  # 上限等於下限加上步寬 SET upper = lower + step;  # 還是和上面的方法一樣,只是多了post_id的限定范圍 UPDATE post AS a SET comment_count = (SELECT count(*) FROM comment WHERE post_id=a.post_id) WHERE post_id >= lower and post_id < upper;  # 更新下限 SET lower = upper; END WHILE; END; // DELIMITER ;

最后,調用一遍這個存儲過程

call UpdateCount();

每次會更新1萬條數據,也就是更新時暫時鎖住這1萬條,

一般來說,更新1萬條數據執行也是很快的,

所以這樣就避免了整表所有記錄被鎖的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM