Quickly generate digital auxiliary table

        Digital auxiliary table is only an integer column containing the integers from 1 to N sequence values, N is usually very large. MySQL in terms of digital auxiliary table is a powerful tool, often do Cartesian product data sheet and digital auxiliary table when writing SQL statements to create additional lines. It recommends creating a persistent data auxiliary table, and fill the value of a certain amount of data as needed. In fact how to populate the digital auxiliary table does not matter, because only need to run this process again, but still can be optimized for this process. Suppose you want to generate digital data as auxiliary table:

create table nums (a bigint unsigned not null primary key) engine=innodb;

Option One: ordinary inefficient

drop procedure if exists pcreatenums;
delimiter //
create procedure pcreatenums(cnt bigint)
begin
    declare s int default 1;
    set session autocommit=0;
    while s<=cnt do
        insert into nums values(s);
        set s=s+1;
    end while;
    commit;
end;
//

        This stored procedure is not very simple, is a cycle, each one inserted data, the number of rows of data generated as the number of cycles. In my environment to perform this process generates one million lines need to perform close to 1 minute 24 seconds. The reason is that the efficiency is not high insert statement is executed 1,000,000.
 

mysql> call pcreatenums(1000000);
Query OK, 0 rows affected (1 min 24.39 sec)

Method Two: Efficient iterative

drop procedure if exists pcreatenums;
delimiter //
create procedure pcreatenums(cnt int)
begin
    declare s int default 1;
    set session autocommit=0;
    insert into nums select s;
    while s<=cnt do
        insert into nums select a+s from nums where a+s <=cnt;
        set s=s*2;
    end while;
    commit;
end;
//

        The execution took less than less than 17 seconds.

mysql> call pcreatenums(1000000);
Query OK, 0 rows affected (16.53 sec)

        In this storage process, the variable s to save the number of rows in the table inserted nums. Beginning of the loop to a data insertion, and when s is equal to the number of rows is less than the execution cycle to be generated. In each iteration, the process of the current values ​​of all row nums table plus s is inserted before nums table. Thus the number of rows in the insertion cycle of a power of 2 increments, insert statement is executed only 21 times, which further comprises as a first seed data once inserted. Therefore, the execution speed of this process soon.

Method three: the first generation

set session cte_max_recursion_depth=1000000;
insert into nums 
with recursive temp (n) as (select 1 union all select n+1 from temp where n < 1000000) select n from temp;

        This method utilizes the CTE (Common Table Expressions) function provided by MySQL 8, all of the data generated recursively disposable, takes less than 13 seconds, the performance is further improved quarter.

mysql> insert into nums 
    -> with recursive temp (n) as (select 1 union all select n+1 from temp where n < 1000000) select n from temp;
Query OK, 1000000 rows affected (12.28 sec)
Records: 1000000  Duplicates: 0  Warnings: 0

        CTE can achieve similar in Oracle connect by recursive function, but more powerful, able to solve very complex inquiries. https://dev.mysql.com/doc/refman/8.0/en/with.html is MySQL official documentation of the CTE.

Published 370 original articles · won praise 599 · Views 2.18 million +

Guess you like

Origin blog.csdn.net/wzy0623/article/details/97891073