随机获取不重复记录的高效SQL语句和一次性往表中添加大量测试数据你真的了解吗?

一、主题研究来源:最近在做一个随机组卷的功能,试题类型有单选题、多选题、判断题、简答题和应用题,该部分的业务需求是根据随机组卷规则,也就是各类型题规定需选多少道,对应在数据库中随机获取不重复的记录数。

二、需求说明:根据题库类型、试题类型和查询记录数在数据库随机查询不重复的记录进行返回。以下sql语句中的试题类型、题库类型以及随机返回记录数都分别设置为1(单选题),8(一级题库),5。

三、根据需求亲试研究给出针对Mysql数据库以下四种SQL语句(供君参考):

提示:1.测试数据为50万条,每条sql性能测试十次取平均值

          2.以下四种sql语句耗时由高到低进行排列 

One/Sql:1.耗时最少,位于性能杀手排行榜榜首  

                 2.测试十次耗时:0.00026  0.00026  0.00030 0.00024  0.00023  0.00024  0.00022  0.00042  0.00024  0.00025

                 3.十次测试平均时间:0.000266

                 4.查出记录的主键ID是有序排列的

#question_test:表名  q_bank_type:试题库类型  question_type:试题类型  
SELECT t1.id,t1.title,t2.id FROM question_test AS t1 JOIN(SELECT ROUND(RAND() * (SELECT MAX(id) FROM question_test)) AS id) AS t2 
WHERE t1.id >= t2.id AND t1.q_bank_type=8 AND t1.question_type =1
ORDER BY t1.id ASC LIMIT 5;

One/Explain:1.SELECT MAX(id) FROM question_test 从试题表中获取最大的Id值

                       2.RAND() * (SELECT  MAX(id)  FROM  question_test  随机获取0到最大值之间的数(单独测试前面加上SELECT)

                       3.SELECT ROUND(RAND() * (SELECT MAX(id) FROM question_test)) 四舍五入随机获取0到最大值之间的数

                       4.JOIN()主要把满足WHERE条件的question_test表记录 和 JOIN括号里获得的数一个个进行拼接返回

                       5.ORDER BY 语句对以上结果集按表主键进行排序,Limit 5 表示查五条

One/Image:

随机获取不重复记录的高效SQL语句和一次性往表中添加大量测试数据你真的了解吗?_第1张图片

 

Two/Sql:1.耗时位于性能杀手排行榜第二位

                 2.测试十次耗时:0.000346  0.000272  0.000262 0.000274 0.000251 0.000259 0.000273 0.000250 0.000272 0.000345

                 3.测试十次平均时间:0.000280

                 4.查出记录的主键ID是有序排列的

#question_test:表名  q_bank_type:试题库类型  question_type:试题类型 
SELECT t1.id,t1.title,t2.id FROM question_test AS t1 JOIN(SELECT ROUND(RAND()* ((SELECT MAX(id) FROM question_test) - (SELECT MIN(id) FROM question_test)) 
+ (SELECT MIN(id) FROM question_test)) AS id) AS t2
WHERE t1.id >= t2.id AND AND t1.q_tank_type=8 AND t1.question_type =1 ORDER BY t1.id LIMIT 5;

Two/Explain:没明白请参照第一条SQL的解析模式,一步步进行分析吧!

Two/Image:

随机获取不重复记录的高效SQL语句和一次性往表中添加大量测试数据你真的了解吗?_第2张图片

 

Three/Sql:1.耗时位于性能杀手排行榜第三位  

                   2.测试十次耗时:1.973573 1.965968 1.935895 1.949896 1.951759  1.947297 1.941950  1.944946  1.977690  1.945701
                   3.十次平均测试时间:1.9534675

                   4.查出记录的主键ID呈乱序排列的

#question_test:表名  q_bank_type:试题库类型  question_type:试题类型
SELECT id, title FROM question_test WHERE q_bank_type=8 AND question_type =1 ORDER BY RAND() LIMIT 5;

Three/Explain:无

Three/Image:

随机获取不重复记录的高效SQL语句和一次性往表中添加大量测试数据你真的了解吗?_第3张图片

 

Four/Sql:1.耗时位于性能杀手排行榜榜末

                  2.测试十次耗时:100.854251 70.259152 117.024592 76.072386 74.670738  74.066505  73.781441  43.795168 83.694435 84.508763

                  3.十次测试平均时间:79.872743

                  4.查出记录的主键ID呈乱序排列的 且查询的时候电脑风扇加速转动

#question_test:表名  q_bank_type:试题库类型  question_type:试题类型
SELECT id,title FROM `question_test` 
WHERE  q_bank_type=8 AND question_type =1 AND id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `question_test`) 
ORDER BY id LIMIT 5;

Four/Explain:FLOOR() 为取整函数,其他部分请参照第一条SQL的解析模式

Four/Image:

随机获取不重复记录的高效SQL语句和一次性往表中添加大量测试数据你真的了解吗?_第4张图片

SQL总结(从左到右性能):OneSQL  稍大于  TwoSQL   大于  ThreeSQL  远大于  FourSQL

四、如何查看一个sql语句执行完后的耗时呢?

步骤1.每条SQL语句执行完了之后,查询该SQL执行时间请执行该语句:"SHOW profiles;",如果不行,紧接着操作以下步骤2

步骤2.执行SQL语句:" SET profiling=1",之后每执行完一条SQL语句,再执行该语句:"SHOW profiles;",就可以查看耗时了

五、如何往一个表中一次性添加大量测试数据?

步骤1.清空表记录语句:TRUNCATE question_test;

步骤2.创建存储过程语句,请把以下语句一起执行:

#创建存储过程,注意以下语句一起执行
DELIMITER &&     
CREATE PROCEDURE quetion_test()        
BEGIN
DECLARE i INT;        
SET i=1;
WHILE i<500000 DO        
    INSERT INTO question_test (`title`,`question_type`,`q_tank_type`,`score`,`level`,`difficult`,`correct`,`create_user`,`status`,`create_time`,`deleted`)
    VALUES(CONCAT('试题',i),1,8,20,5,1,'D',1,1,'2020-06-09 10:05:29','\0'); 
SET i=i+1;        
END WHILE;
END 
&&

步骤3.执行存储过程语句:"CALL quetion_test();"

提示:经过以上三步骤,就往question_test表里一次性成功添加了50万条测试数据了;如果需要删除已存在的存储过程,执行SQL语句:"DROP PROCEDURE IF EXISTS quetion_test;" 即可!

六、总结

以上SQL语句都经过亲自挑选并在SQLyang中一一进行测试,可以放心使用;有啥不足的地方,欢迎随时指正!

你可能感兴趣的:(Mysql数据库)