zoukankan      html  css  js  c++  java
  • 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万条数据执行也是很快的,

    所以这样就避免了整表所有记录被锁的问题。

  • 相关阅读:
    VS缓冲区溢出,未对变量进行检查
    Mutex与Event控制互斥事件的使用详解
    error LNK2019: 无法解析的外部符号
    [转] 兼容IE和Firefox的设为首页和收藏的Javascript代码
    [转]超时时间以到,但尚未从池中获取连接
    Datalist的嵌套使用
    由服务器端向客户端输出脚本
    几个国外的XHTML模板站,DIV+CSS模板下载(转)
    gridview隐藏某一列
    [转]简单谈基于SQL SERVER 分页存储过程的演进
  • 原文地址:https://www.cnblogs.com/microtiger/p/11813533.html
Copyright © 2011-2022 走看看