mysql千万级测试1亿数据的分页分析测试

2024-03-13 15:58

本文主要是介绍mysql千万级测试1亿数据的分页分析测试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文为本人最近利用几个小时才分析总结出的原创文章,希望大家转载,但是要注明出处

http://blog.sina.com.cn/s/blog_438308750100im0e.html

有什么问题可以互相讨论:yubaojian0616@163.com 于堡舰

 

  上一篇文章我们测试一些orderby查询和分页查询的一些基准性能,现在我们来分析一下条件索引查询的结果集的测试

 

现在我们继续进行一个测试相同的表结构插入1亿条数据这次用到的是Innodb表引擎,表名有些变化,这里为甚要新建一个表的很重要元素是原来的那张表是每个uid=1来做的索引,这次uid是1...10不等的数每种1千万条记录
CREATE TABLE `ipdata` (
   `id` int(11) NOT NULLAUTO_INCREMENT,
   `uid` int(8) NOT NULL DEFAULT'0',
   `ipaddress` varchar(50) NOTNULL,
   `source` varchar(255) DEFAULTNULL,
   `track` varchar(255) DEFAULTNULL,
   `entrance` varchar(255)DEFAULT NULL,
   `createdtime` datetime NOTNULL DEFAULT '0000-00-00 00:00:00',
   `createddate` date NOT NULLDEFAULT '0000-00-00',
   PRIMARY KEY (`id`),
   KEY `uid` (`uid`)
} ENGINE=InnoDB AUTO_INCREMENT=100004857 DEFAULT CHARSET=utf8
我开启了Innodb的线程数为128,因为innodb是行级别锁定,并发处理能力很强我开启100线程每个线程大小为100万记录插入时间如下
JDBC插入100w条数据此线程用时:9300984ms
JDBC插入100w条数据此线程用时:9381203ms
JDBC插入100w条数据此线程用时:9412343ms
JDBC插入100w条数据此线程用时:9442046ms
JDBC插入100w条数据此线程用时:9449828ms
JDBC插入100w条数据此线程用时:9484703ms
JDBC插入100w条数据此线程用时:9528093ms
JDBC插入100w条数据此线程用时:9533359ms
JDBC插入100w条数据此线程用时:9534296ms
JDBC插入100w条数据此线程用时:9539718ms
JDBC插入100w条数据此线程用时:9541750ms
JDBC插入100w条数据此线程用时:9636406ms
JDBC插入100w条数据此线程用时:9695093ms
JDBC插入100w条数据此线程用时:9806890ms
JDBC插入100w条数据此线程用时:9895500ms
JDBC插入100w条数据此线程用时:9989750ms
JDBC插入100w条数据此线程用时:10012312ms
JDBC插入100w条数据此线程用时:10037250ms
JDBC插入100w条数据此线程用时:10092796ms
JDBC插入100w条数据此线程用时:11993187ms
JDBC插入100w条数据此线程用时:12033203ms
JDBC插入100w条数据此线程用时:12068453ms
JDBC插入100w条数据此线程用时:12133625ms
JDBC插入100w条数据此线程用时:12212953ms
JDBC插入100w条数据此线程用时:12253421ms
JDBC插入100w条数据此线程用时:12284968ms
JDBC插入100w条数据此线程用时:12296421ms
JDBC插入100w条数据此线程用时:12366828ms
JDBC插入100w条数据此线程用时:12388093ms
JDBC插入100w条数据此线程用时:12389656ms
JDBC插入100w条数据此线程用时:12396625ms
JDBC插入100w条数据此线程用时:12417921ms
JDBC插入100w条数据此线程用时:12431000ms
JDBC插入100w条数据此线程用时:12432875ms
JDBC插入100w条数据此线程用时:12434703ms
JDBC插入100w条数据此线程用时:12455218ms
JDBC插入100w条数据此线程用时:12457109ms
JDBC插入100w条数据此线程用时:12484218ms
JDBC插入100w条数据此线程用时:12518375ms
JDBC插入100w条数据此线程用时:12519015ms
JDBC插入100w条数据此线程用时:12521109ms
JDBC插入100w条数据此线程用时:12521515ms
JDBC插入100w条数据此线程用时:12537343ms
JDBC插入100w条数据此线程用时:12539421ms
JDBC插入100w条数据此线程用时:12544250ms
JDBC插入100w条数据此线程用时:12559234ms
JDBC插入100w条数据此线程用时:12567484ms
JDBC插入100w条数据此线程用时:12574109ms
JDBC插入100w条数据此线程用时:12579156ms
JDBC插入100w条数据此线程用时:12638046ms
JDBC插入100w条数据此线程用时:12693047ms
JDBC插入100w条数据此线程用时:12722906ms
JDBC插入100w条数据此线程用时:12728781ms
JDBC插入100w条数据此线程用时:12732546ms
JDBC插入100w条数据此线程用时:12748265ms
JDBC插入100w条数据此线程用时:12757421ms
JDBC插入100w条数据此线程用时:12761375ms
JDBC插入100w条数据此线程用时:12765312ms
JDBC插入100w条数据此线程用时:12788359ms
JDBC插入100w条数据此线程用时:12802765ms
JDBC插入100w条数据此线程用时:12810484ms
JDBC插入100w条数据此线程用时:12811062ms
JDBC插入100w条数据此线程用时:12811796ms
JDBC插入100w条数据此线程用时:12812843ms
JDBC插入100w条数据此线程用时:12829671ms
JDBC插入100w条数据此线程用时:12830296ms
JDBC插入100w条数据此线程用时:12840000ms
JDBC插入100w条数据此线程用时:12840890ms
JDBC插入100w条数据此线程用时:12850312ms
JDBC插入100w条数据此线程用时:12856671ms
JDBC插入100w条数据此线程用时:12858609ms
JDBC插入100w条数据此线程用时:12860125ms
JDBC插入100w条数据此线程用时:12861750ms
JDBC插入100w条数据此线程用时:12864125ms
JDBC插入100w条数据此线程用时:12875609ms
JDBC插入100w条数据此线程用时:12875781ms
JDBC插入100w条数据此线程用时:12900859ms
JDBC插入100w条数据此线程用时:12906812ms
JDBC插入100w条数据此线程用时:12909656ms
JDBC插入100w条数据此线程用时:12913375ms
JDBC插入100w条数据此线程用时:12915609ms
JDBC插入100w条数据此线程用时:12917562ms
JDBC插入100w条数据此线程用时:12918000ms
JDBC插入100w条数据此线程用时:12919468ms
JDBC插入100w条数据此线程用时:12922093ms
JDBC插入100w条数据此线程用时:12922843ms
JDBC插入100w条数据此线程用时:12924375ms
JDBC插入100w条数据此线程用时:12925734ms
JDBC插入100w条数据此线程用时:12925781ms
JDBC插入100w条数据此线程用时:12931140ms
JDBC插入100w条数据此线程用时:12934562ms
JDBC插入100w条数据此线程用时:12934828ms
JDBC插入100w条数据此线程用时:12935281ms
JDBC插入100w条数据此线程用时:12936953ms
JDBC插入100w条数据此线程用时:12937218ms
JDBC插入100w条数据此线程用时:12937406ms
JDBC插入100w条数据此线程用时:12937765ms
JDBC插入100w条数据此线程用时:12939125ms
JDBC插入100w条数据此线程用时:12940281ms
JDBC插入100w条数据此线程用时:12941828ms
大概一共用了2个多小时内容为1亿条数据mysql的innodb中文件大小为 11.7 GB (12,660,506,624字节);
首先来看看in查询
SELECT * FROM ipdata WHERE idIN(112358,201023,100020,100001,10000,100000,1000000,10000000,100000000);141ms
SELECT * FROM ipdata WHERE idIN(12345,123456,1234567,12345678,987654,789654,1236985,852963,9745621,78965412);141ms
看来in的查询还算理想,
然后我们进行分页必要查询不排序
SELECT id FROM ipdata WHERE uid=1 LIMIT 1,10; 31ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 10,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 100,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 1000,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 10000,10; 47ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 100000,10; 235ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 1000000,10; 1.438s;
SELECT id FROM ipdata WHERE uid=1 LIMIT 5000000,10; 5.422s;
SELECT id FROM ipdata WHERE uid=1 LIMIT 10000000,10; 9.562s;无返回结果
SELECT id FROM ipdata WHERE uid=1 LIMIT 9999990,10; 10.953s;
符合上一篇的结论mysql越向后越慢,但是整体来说是可以接受的,毕竟分页到最后一页虽然用到了10秒钟,但是后台人员不可能到最后去看,第二呢,10秒后台人员也算可以接受级别;


分页排序查询
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1,10;0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10,10;0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100,10;0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000,10;0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10000,10;47ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100000,10;266ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000000,10;1.594s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 5000000,10;5.625s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id DESC LIMIT5000000,10; 11.235s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT10000000,10; 11.562s 无返回结果
SELECT id FROM ipdata WHERE uid=1 ORDER BY ID ASC LIMIT 9999990,10;11.719s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY ID DESC LIMIT9999990,10; 18.719s;
结论是如果单查找id,order by的时间比较可观,但是可见正序和倒序时间不同.

 

返回全部结果查询"*"
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1,10;109ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10,10;0ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100,10;16ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000,10;63ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10000,10;356ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100000,10;2.969s;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000000,10;30.766s;
selectid,uid,ipaddress,source,track,entrance,createdtime,createddate fromipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000000,10; 29.953s;
...下面的就不测试了,已经难以接受了
结论SELECT id 要比SELECT *快了不少至少在大的结果面前;

 

结果count测试
SELECT COUNT(*) FROM ipdata WHERE uid=1; 12.281s;
SELECT COUNT(*) FROM ipdata WHERE uid=2; 12.250s;
....
SELECT COUNT(*) FROM ipdata WHERE uid=10; 11.453s;
count级别大概是10多秒左右返回都是1000万;

Count(id)测试
SELECT COUNT(id) FROM ipdata WHERE uid=1; 10.281s;
SELECT COUNT(id) FROM ipdata WHERE uid=2; 10.531s;
....
SELECT COUNT(id) FROM ipdata WHERE uid=10; 12.531s;
Count(id)这里我不知道是机器原因可能测试不是十分准确,总之相差不大,不知道是否mysql默认通过唯一主键来count,如果*和id差不多都方便我还是推荐id,呵呵


   这样我们可以通过SELECT id来得到id列表,然后通过in来得到相应的记录,可见是可行的;还有在这次测试中我们通过uid这个属性来过滤掉了90%的结果集,如果根据95%过滤理想化可能还有点欠缺,但是根据80%过滤原则就不同了,至少这个索引还是理想的,过滤掉的内容看来mysql就可以算到千万级别的用时了。其实这里面的时间不代表真实时间,毕竟机器也是我们办公室一台pc电脑,数据也比较小,这里我只是有时间来测试一下千万条乃至上亿条数据的处理能力,到服务器上应该要比这个快很多,毕竟磁盘io差距大,而且cpu也有差距,
 
总结
 1.mysql千万级别数据肯定是没问题的,毕竟现在的流向web2.0网站大部分是mysql的
 2.合理分表也是必须的,主要涉及横向分表与纵向分表,如把大小字段分开,或者每100万条记录在一张表中等等,像上面的这个表可以考虑通过uid的范围分表,或者通过只建立索引表,去掉相对大的字段来处理.
 3.count()时间比较长,但是本身是可以缓存在数据库中或者缓存在程序中的,因为我们当时使用在后台所以第一页比较慢但是后面比较理想
 4.SELECT id 相对SELECT *差距还是比较大的,可以通过上面的方法来使用SELECT id + SELECT * ... IN 查询来提高性能
 5.必要的索引是必须的,还是要尽量返回5%-20%的结果级别其中小于5%最理想;
 6.mysql分页的前面几页速度很快,越向后性能越差,可以考虑只带上一页,下一页不带页面跳转的方法,呵呵这个比较垃圾但是也算是个方案,只要在前后多查一条就能解决了.比如100,10你就差99,12呵呵,这样看看前后是否有结果.
 7.前台还是要通过其他手段来处理,比如lucene/Solr+mysql结合返回翻页结果集,或者上面的分表
 8. 1亿的数据还在我们这里大家可以充分考虑搜索条件我帮大家测试哈哈。

 

接下来我将要测试一些关于1亿+的用户数据表的解决方案,及大数据的搜索方案通过lucene/solr+mysql

这篇关于mysql千万级测试1亿数据的分页分析测试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/805394

相关文章

浅谈mysql的not exists走不走索引

《浅谈mysql的notexists走不走索引》在MySQL中,​NOTEXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引,下面就来介绍一下mysql的notexists走不走索... 在mysql中,​NOT EXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引。以下

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

MySQL 中的 CAST 函数详解及常见用法

《MySQL中的CAST函数详解及常见用法》CAST函数是MySQL中用于数据类型转换的重要函数,它允许你将一个值从一种数据类型转换为另一种数据类型,本文给大家介绍MySQL中的CAST... 目录mysql 中的 CAST 函数详解一、基本语法二、支持的数据类型三、常见用法示例1. 字符串转数字2. 数字

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语