首页 > 其他分享 >一千万的数据,你是怎么查询的?

一千万的数据,你是怎么查询的?

时间:2024-03-12 19:59:48浏览次数:21  
标签:log utf8mb4 一千万 查询 user operation NULL 数据 SELECT

图片

 准备数据

2.1 创建表

CREATE TABLE `user_operation_log`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `op_data` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr4` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr6` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr7` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr8` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr9` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr10` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr11` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `attr12` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

2.2 造数据脚本

采用批量插入,效率会快很多,而且每1000条数就commit,数据量太大,也会导致批量插入效率慢

DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `batch_insert_log`()
BEGIN
  DECLARE i INT DEFAULT 1;
  DECLARE userId INT DEFAULT 10000000;
 set @execSql = 'INSERT INTO `big_data`.`user_operation_log`(`user_id`, `ip`, `op_data`, `attr1`, `attr2`, `attr3`, `attr4`, `attr5`, `attr6`, `attr7`, `attr8`, `attr9`, `attr10`, `attr11`, `attr12`) VALUES';
 set @execData = '';
  WHILE i<=10000000 DO
   set @attr = "rand_string(50)";
  set @execData = concat(@execData, "(", userId + i, ", '110.20.169.111', '用户登录操作'", ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ")");
  if i % 1000 = 0
  then
     set @stmtSql = concat(@execSql, @execData,";");
    prepare stmt from @stmtSql;
    execute stmt;
    DEALLOCATE prepare stmt;
    commit;
    set @execData = "";
   else
     set @execData = concat(@execData, ",");
   end if;
  SET i=i+1;
  END WHILE;
END
DELIMITER ;
delimiter $$
create function rand_string(n INT) 
returns varchar(255) #该函数会返回一个字符串
begin 
#chars_str定义一个变量 chars_str,类型是 varchar(100),默认值'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
 declare chars_str varchar(100) default
   'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
 declare return_str varchar(255) default '';
 declare i int default 0;
 while i < n do 
   set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
   set i = i + 1;
   end while;
 return return_str;
end $$

2.3 执行存储过程函数

模拟数据1000W

SELECT count(1) FROM `user_operation_log`;

图片

image-20230331163130669

2.4 普通分页查询

MySQL分页查询语法如下:

SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset

图片

下面我们开始测试查询结果:

SELECT * FROM `user_operation_log` LIMIT 10000, 10;

查询3次时间分别为:

图片

image-20230331164216737

图片

image-20230331164250745

图片

image-20230331164319760

图片

SELECT * FROM `user_operation_log` LIMIT 10000, 10;
SELECT * FROM `user_operation_log` LIMIT 10000, 100;
SELECT * FROM `user_operation_log` LIMIT 10000, 1000;
SELECT * FROM `user_operation_log` LIMIT 10000, 10000;
SELECT * FROM `user_operation_log` LIMIT 10000, 100000;
SELECT * FROM `user_operation_log` LIMIT 10000, 1000000;

图片

图片

相同数据量,不同偏移量

SELECT * FROM `user_operation_log` LIMIT 100, 100;
SELECT * FROM `user_operation_log` LIMIT 1000, 100;
SELECT * FROM `user_operation_log` LIMIT 10000, 100;
SELECT * FROM `user_operation_log` LIMIT 100000, 100;
SELECT * FROM `user_operation_log` LIMIT 1000000, 100;

图片

从上面结果可以得出结束:偏移量越大,花费时间越长

3 如何优化

图片

3.1 优化数据量大的问题

SELECT * FROM `user_operation_log` LIMIT 1, 1000000
SELECT id FROM `user_operation_log` LIMIT 1, 1000000
SELECT id, user_id, ip, op_data, attr1, attr2, attr3, attr4, attr5, attr6, attr7, attr8, attr9, attr10, attr11, attr12 FROM `user_operation_log` LIMIT 1, 1000000

查询结果如下:

图片

图片

图片

图片

图片

  • 3.2 优化偏移量大的问题

3.2.1 采用子查询方式

我们可以先定位偏移位置的 id,然后再查询数据

SELECT id FROM `user_operation_log` LIMIT 1000000, 1;
SELECT * FROM `user_operation_log` WHERE id >= (SELECT id FROM `user_operation_log` LIMIT 1000000, 1) LIMIT 10;

查询结果如下:

图片

图片

EXPLAIN SELECT id FROM `user_operation_log` LIMIT 1000000, 1;
EXPLAIN SELECT * FROM `user_operation_log` WHERE id >= (SELECT id FROM `user_operation_log` LIMIT 1000000, 1) LIMIT 10;

奇怪,走了索引啊,而且是主键索引,如下

图片

图片

带着十万个为什么和千万个不甘心,尝试给主键再加一层唯一索引

ALTER TABLE `big_data`.`user_operation_log` 
ADD UNIQUE INDEX `idx_id`(`id`) USING BTREE;

图片

图片

天啊,这查询效率的差距不止十倍!!!

再次EXPLAIN分析一下:

图片

图片

命中的索引不一样,命中唯一索引的查询,效率高出不止十倍。

结论:

图片

但是上面的方法只适用于**==id是递增==**的情况,如果id不是递增的,比如雪花算法生成的id,得按照下面的方式:

注意:

  1. 某些 mysql 版本不支持在 in 子句中使用 limit,所以采用了多个嵌套select

  2. 但这种缺点是分页查询只能放在子查询里面

SELECT * FROM `user_operation_log` WHERE id IN (SELECT t.id FROM (SELECT id FROM `user_operation_log` LIMIT 1000000, 10) AS t);

查询所花费时间如下:

图片

image-20230331201356087

EXPLAIN一下

EXPLAIN SELECT * FROM `user_operation_log` WHERE id IN (SELECT t.id FROM (SELECT id FROM `user_operation_log` LIMIT 1000000, 10) AS t);

图片

image-20230331201459758

3.2.2 采用 id 限定方式

图片

SELECT * FROM `user_operation_log` WHERE id between 1000000 AND 1000100 LIMIT 100;
SELECT * FROM `user_operation_log` WHERE id >= 1000000 LIMIT 100;

图片

image-20230331202058138

图片

EXPLAIN SELECT * FROM `user_operation_log` WHERE id between 1000000 AND 1000100 LIMIT 100;
EXPLAIN SELECT * FROM `user_operation_log` WHERE id >= 1000000 LIMIT 100;

图片

图片

因此,针对分页查询,偏移量大导致查询慢的问题:

图片

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

标签:log,utf8mb4,一千万,查询,user,operation,NULL,数据,SELECT
From: https://blog.csdn.net/weixin_45334346/article/details/136661501

相关文章

  • 阳光保险MySQL数据库平稳迁移OceanBase,稳定运营超700天
    作者简介:车东兴:于阳光保险就职,深耕保险行业的IT领域长达12年,对保险领域的基础架构实践有深刻的理解与掌握。熟悉多款数据库,具有丰富的数据库运维经验。王华城:于阳光保险就职,10多年一直从事MySQL数据库的运维工作,在本地及云上数据库部署运维经验丰富,近年来对与MyS......
  • HDFS读数据流程、NN和2NN工作机制、DataNode工作机制、数据完整性
    HDFS读数据流程    事件描述:客户端要下载一个200m的数据文件,hdfs是如何读取的。   两个对象:一个客户端、一个集群   流程:       1.客户端创建一个分布式文件系统(DistributedFileSystem),向集群NameNode请求下载文件。       ......
  • 【数据结构】排序
    文章目录一、排序的概念及引用1、排序的概念2、常见的排序算法二、常见排序算法的实现1、插入排序2、直接插入排序一、排序的概念及引用1、排序的概念排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。稳定性:假定在待排......
  • 【数据结构】堆
    目录1、树的概念及结构1.1树的概念1.2树的相关概念1.3树的结构定义2、二叉树的概念及结构2.1二叉树的概念2.2特殊的二叉树2.3二叉树的性质3、堆的概念及结构3.1二叉树的存储方式3.1.1顺序存储3.1.2链式存储3.2堆的概念及结构4、堆的代码实现4.1堆的初始化(建堆)......
  • Elasticsearch 如何保证写入过程中不丢失数据的
    丢失数据的本质在本文开始前,首先明白一个点,平时我们说的组件数据不丢失究竟是在指什么,如果你往ES写入数据,ES返回给你写入错误,这个不算数据丢失。如果你往ES写入数据,ES返回给你成功,但是后续因为ES节点重启或宕机导致写入的数据不见了,这个才叫数据丢失。简而言之,丢失数据的本质是E......
  • PowerShell 定时备份MySQL数据
    #========================================================#Function:备份MySQL数据库#ReleaseVersion:v0.0.3#ReleaseDate:2020年8月17日#Author:panda666#Website:www.panda666.com#=====================================......
  • Python毕业设计 人工智能与大数据专业毕业设计(论文)选题题目
    目录前言毕设选题人工智能大数据选题迷茫选题的重要性更多选题指导最后 前言  ......
  • Python基础_多进程数据共享
    Python基础_多进程数据共享一、多进程数据共享二、使用multiprocessing.Manager对象三、使用multiprocessing.Value和multiprocessing.Array四、使用管道和队列五、使用共享内存六、注意事项一、多进程数据共享Python中,多进程之间的数据共享是一个复杂的主题,因为每个......
  • 关于android stdio连接mysql数据库出现过的问题
    根据网上的资料连接mysql数据库的步骤有:1.导入mysql连接jar包我的androidstdio文件里没有libs文件夹,就在build创建了一个,选择jar包,aslibrary,重启下进程,就会生成一些文件2.在mainfest.xml文件下加入网络权限<uses-permissionandroid:name="android.permission.INTERNET"/>......
  • es聚合查询自动补0----java代码
    ES语句GET/event_log_hulianwang_v3/_search{"size":0,"query":{"bool":{"must":[{"term":{"event_type.keyword":"终端事件&qu......