Use Mysql timing + stored procedure to create temporary table statistics

1. A brief introduction to mysql timing tasks

The timed task of mysql is implemented using event (event). Since version 5.1.6 of mysql, this function has been added - event scheduler (event scheduler), which can execute a task accurately every second. In some data real-time It is very useful in scenes with relatively high performance requirements. Next, I will use the event event of mysql to realize timing statistics.

2. Preparations

(1) Check whether the timing policy is enabled

show variables like '%event_sche%';

The execution results are as follows

ON means it is in the open state, if it is OFF, it means it is in the closed state, assuming it is in the closed state, just use the following sql statement to open and close.

--开启定时调度策略(下面两个语句都可以)
set global event_scheduler=1;
set global event_scheduler = on;

--关闭定时调度策略(下面两个语句都可以)
set global event_scheduler=0;
set global event_scheduler = off;

Turn off the timing scheduling strategy sql execution result:

Enable timing scheduling strategy sql execution results:

(2) Execute the user information table and user order table sql script

# 用户信息表
CREATE TABLE `user_info` (
    `id` INT ( 11 ) NOT NULL AUTO_INCREMENT COMMENT 'ID',
    `name` VARCHAR ( 30 ) NOT NULL COMMENT '用户名',
    `phone` VARCHAR ( 11 ) NOT NULL COMMENT '手机号',
    `status` TINYINT ( 1 ) NULL DEFAULT NULL COMMENT '用户状态:停用0,启动1',
    `create_time` datetime NOT NULL COMMENT '创建时间',
    PRIMARY KEY ( `id` ) USING BTREE 
) ENGINE = INNODB AUTO_INCREMENT = 10001 CHARACTER 
SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户信息表';

# 用户订单表
CREATE TABLE `user_order`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `order_num` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单编号',
  `user_id` int(11) NOT NULL COMMENT '用户ID',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `idx_order_num`(`order_num`) USING BTREE COMMENT '订单编号唯一'
) ENGINE = INNODB AUTO_INCREMENT = 10001 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户订单表';

(3) Execute the sql script for inserting test data

# 向用户信息表中插入三条测试数据
INSERT INTO `user_info` (`id`, `name`, `phone`, `status`, `create_time`) VALUES (10001, '张三', '13900669010', 1, '2023-03-14 17:01:42');
INSERT INTO  `user_info` (`id`, `name`, `phone`, `status`, `create_time`) VALUES (10002, '李四', '13900669111', 1, '2023-03-14 17:01:42');
INSERT INTO  `user_info` (`id`, `name`, `phone`, `status`, `create_time`) VALUES (10003, '王五', '13900669876', 1, '2023-03-14 17:01:42');

# 向用户订单表中插入八条测试数据
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10001, 'dingdan001', 10002, '2023-03-14 17:03:40');
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10002, 'dingdan002', 10003, '2023-03-14 17:03:40');
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10003, 'dingdan003', 10002, '2023-03-14 17:03:40');
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10004, 'dingdan004', 10002, '2023-03-14 17:03:40');
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10005, 'dingdan005', 10003, '2023-03-14 17:03:40');
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10006, 'dingdan006', 10003, '2023-03-14 17:03:40');
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10007, 'dingdan007', 10002, '2023-03-14 17:03:40');
INSERT INTO  `user_order` (`id`, `order_num`, `user_id`, `create_time`) VALUES (10008, 'dingdan008', 10001, '2023-03-14 17:03:40');

(2) The result of script execution in (3):

3. Write stored procedure scripts


DELIMITER //
DROP PROCEDURE
IF
    EXISTS statistics_user_order // CREATE PROCEDURE statistics_user_order () BEGIN
    DECLARE
        temp_table_name VARCHAR ( 60 ) DEFAULT '';
    DECLARE
        suffix VARCHAR ( 10 ) DEFAULT '';
    DECLARE
        old_table_name VARCHAR ( 60 ) DEFAULT NULL;
    SELECT
        table_name INTO old_table_name 
    FROM
        information_schema.`TABLES` 
    WHERE
        table_name LIKE 'temp_statistics_%' 
        AND table_schema = 'db_name'; -- 此处填自己对应的数据库名即可
    IF
        old_table_name IS NOT NULL THEN
        -- execute multiple statements
        -- 如果IF THEN ... END IF块内有多个语句,最好将它们放在一个BEGIN ... END;块中
        BEGIN
                
                SET @drop_sql := CONCAT( 'DROP TABLE ', old_table_name, ';' );
            PREPARE d_sql 
            FROM
                @drop_sql;
            EXECUTE d_sql;
            DEALLOCATE PREPARE d_sql;
            
        END;
        
    END IF;
    SELECT
        DATE_FORMAT( NOW(), '%Y%m%d' ) INTO suffix;
    
    SET temp_table_name = CONCAT( 'temp_statistics_', suffix );
    
    SET @create_sql = CONCAT( 'create table if not exists ', temp_table_name, "(
        `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
        `user_id` INT ( 11 ) NOT NULL COMMENT '用户ID',
        `name` VARCHAR ( 30 ) NOT NULL COMMENT '用户名',
        `number` INT ( 11 ) NOT NULL DEFAULT 0 COMMENT '订单数',
        `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
        PRIMARY KEY ( `id` ) USING BTREE 
    ) ENGINE = INNODB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户订单统计表';" );
    PREPARE pre_stmt 
    FROM
        @create_sql;
    EXECUTE pre_stmt;
    DEALLOCATE PREPARE pre_stmt;
    -- 简单的用set或者declare语句定义变量,然后直接作为sql的表名是不行的,mysql会把变量名当作表名。
    SET @insert_sql = CONCAT( 'INSERT INTO ', temp_table_name, "( `user_id`, `name`, `number` ) SELECT
        i.id AS `user_id`,
        i.`name` AS `name`,
        COUNT( o.user_id ) AS `number` 
        FROM
        user_info i
        LEFT JOIN user_order o ON i.id = o.user_id 
        WHERE
        i.`status` = 1 
        GROUP BY
    i.id;" );
    PREPARE pre_insert 
    FROM
        @insert_sql;
    EXECUTE pre_insert;
    DEALLOCATE PREPARE pre_insert;
    
END // 
DELIMITER;

Script execution result: (Note: Do not forget to change the database in the above stored procedure "AND table_schema = 'db_name'; -- just fill in your corresponding database name here")

The above storage process is mainly divided into three stages

a. Check whether the temporary table exists in the database, and delete the table structure if it exists (remove the old table)

b. Create a new temporary table according to the current time, and add fields to the table structure according to statistical needs

c. Joint table query, count the number of orders owned by each user, and insert them into the temporary table

4. Write and execute scheduled task scripts

In order to let everyone see a more significant effect, set the scheduled task to execute every 10 seconds, that is, the function of this scheduled task is to count the number of orders of the user every 10 seconds.

create event job_statistics -- 是创建名为job_statistics的事件;
on schedule every 10 SECOND -- 创建周期定时的规则,意思是每10s种执行一次;
on completion preserve enable --  是表示创建后就开始生效,不让开始生效设置disable
do call statistics_user_order(); -- 事件要执行的内容,调用了上述的存储过程

Script execution result:

View scheduled tasks:

select * from information_schema.EVENTS;

Script execution result:

View the execution effect of the scheduled task: (see the time difference below, the timing is refreshing)

Stop timing task execution:

ALTER event job_statistics on completion preserve disable;

Continue timing tasks:

ALTER event job_statistics on completion preserve enable;

Guess you like

Origin blog.csdn.net/weixin_42218169/article/details/129565173