`

mysql数据库千万级别数据的查询优化和分页测试

阅读更多

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

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

有什么问题:yubaojian0616@163.com 于堡舰

 

我原来的公司是一家网络游戏公司,其中网站交易与游戏数据库结合通过ws实现的,但是交易记录存放在网站上,级别是千万级别的数据库是mysql数据库.
 
  可能有人会问mysql是否支持千万级数据库,还有既然已经到了这个数据量公司肯定不差,为什么要用mysql而不用oracle这里我做一下解答
  1. mysql绝对支持千万级数据库是可以肯定的,
  2. 为什么选择择mysql呢?
 1> 第一也是最主要的一条是mysql他能做到。
 2> 在第一点前提下以下的就不是太重要了,mysql相对操作简单,测试容易,配置优化也相对容易很多
 3> 我们这里的数据仅仅是为了记录交易保证交易是被记录的,对于查询的还是相对少只有管理后台操作中需要对数据库进行查询
 4> 数据结构简单,而且每条记录都非常小,因为查询速度不管和记录条数有关和数据文件大小也有直接关系.
 5> 我们采用的是大小表的解决办法,每天大概需要插入数据库好几百万条,这里可能还是有人怀疑,其实没问题,如果批量插入我测试的在普通的pc机子上带该一个线程并发我插入的是6千万条记录大概需要“JDBC插入6000W条数据用时:9999297ms”,小表保存最近插入的内容,把几天前的保存到大表中,这里我说的就是大表大概6-7千万条数据;
 
  带着这些疑问和求知欲望咱们来做一个测试,因为在那个时候我也不是dba不知道人家是怎么搞的能够做成这么大的数据量,我们平时叶总探讨一些相关的内容

  1.mysql的数据查询,大小字段要分开,这个还是有必要的,除非一点就是你查询的都是索引内容而不是表内容,比如只查询id等等
  2.查询速度和索引有很大关系也就是索引的大小直接影响你的查询效果,但是查询条件一定要建立索引,这点上注意的是索引字段不能太多,太多索引文件就会很大那样搜索只能变慢,
  3.查询指定的记录最好通过Id进行in查询来获得真实的数据.其实不是最好而是必须,也就是你应该先查询出复合的ID列表,通过in查询来获得数据

  我们来做一个测试ipdatas表:
  CREATE TABLE `ipdatas` (
   `id` INT(11) NOT NULL AUTO_INCREMENT,
   `uid` INT(8) NOT NULL DEFAULT '0',
   `ipaddress` VARCHAR(50) NOT NULL,
   `source` VARCHAR(255) DEFAULT NULL,
   `track` VARCHAR(255) DEFAULT NULL,
   `entrance` VARCHAR(255) DEFAULT NULL,
   `createdtime` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
   `createddate` DATE NOT NULL DEFAULT '0000-00-00',
   PRIMARY KEY (`id`),
   KEY `uid` (`uid`)
  ) ENGINE=MYISAM AUTO_INCREMENT=67086110 DEFAULT CHARSET=utf8;
  这是我们做的广告联盟的推广ip数据记录表,由于我也不是mysql的DBA所以这里咱们仅仅是测试
  因为原来里面有大概7015291条数据

  这里我们通过jdbc的batch插入6000万条数据到此表当中“JDBC插入6000W条数据用时:9999297ms”;
  大概用了两个多小时,这里面我用的是batch大小大概在1w多每次提交,还有一点是每次提交的数据都很小,而且这里用的myisam数据表,因为我需要知道mysql数据库的大小以及索引数据的大小结果是
  ipdatas.MYD 3.99 GB (4,288,979,008 字节)
  ipdatas.MYI 1.28 GB (1,377,600,512 字节)
  这里面我要说的是如果真的是大数据如果时间需要索引还是最好改成数字字段,索引的大小和查询速度都比时间字段可观。

  步入正题:
  1.全表搜索
 返回结构是67015297条数据
   SELECT COUNT(id) FROM ipdatas;
   SELECT COUNT(uid) FROM ipdatas;
   SELECT COUNT(*) FROM ipdatas;
   首先这两个全表数据查询速度很快,mysql中包含数据字典应该保留了数据库中的最大条数
 查询索引条件
   SELECT COUNT(*) FROM ipdatas WHERE uid=1;   返回结果时间:2分31秒594
   SELECT COUNT(id) FROM ipdatas WHERE uid=1;  返回结果时间:1分29秒609
   SELECT COUNT(uid) FROM ipdatas WHERE uid=1; 返回结果时间:2分41秒813
   第二次查询都比较快因为mysql中是有缓存区的所以增大缓存区的大小可以解决很多查询的优化,真可谓缓存无处不在啊在程序开发中也是层层都是缓存
 查询数据
   第一条开始查询
   SELECT * FROM ipdatas ORDER BY id DESC LIMIT 1,10 ; 31毫秒
   SELECT * FROM ipdatas LIMIT 1,10 ; 15ms
  
   第10000条开始查询
   SELECT * FROM ipdatas ORDER BY id ASC LIMIT 10000,10 ; 266毫秒
   SELECT * FROM ipdatas LIMIT 10000,10 ; 16毫秒

   第500万条开始查询
   SELECT * FROM ipdatas LIMIT 5000000,10 ;11.312秒
   SELECT * FROM ipdatas ORDER BY id ASC LIMIT 5000000,10 ; 221.985秒
   这两条返回结果完全一样,也就是mysql默认机制就是id正序然而时间却大相径庭

   第5000万条开始查询
   SELECT * FROM ipdatas LIMIT 60000000,10 ;66.563秒 (对比下面的测试)
   SELECT * FROM ipdatas ORDER BY id ASC LIMIT 50000000,10; 1060.000秒
   SELECT * FROM ipdatas ORDER BY id DESC LIMIT 17015307,10; 434.937秒
   第三条和第二条结果一样只是排序的方式不同但是用时却相差不少,看来这点还是不如很多的商业数据库,像oracle和sqlserver等都是中间不成两边还是没问题,看来mysql是开始行越向后越慢,这里看来可以不排序的就不要排序了性能差距巨大,相差了20多倍

 查询数据返回ID列表
   第一条开始查
   select id from ipdatas order by id asc limit 1,10; 31ms
   SELECT id FROM ipdatas LIMIT 1,10 ; 0ms
  
   第10000条开始
   SELECT id FROM ipdatas ORDER BY id ASC LIMIT 10000,10; 68ms
   select id from ipdatas limit 10000,10;0ms

   第500万条开始查询
   SELECT id FROM ipdatas LIMIT 5000000,10; 1.750s
   SELECT id FROM ipdatas ORDER BY id ASC LIMIT 5000000,10;14.328s

   第6000万条记录开始查询
   SELECT id FROM ipdatas LIMIT 60000000,10; 116.406s
   SELECT id FROM ipdatas ORDER BY id ASC LIMIT 60000000,10; 136.391s

   select id from ipdatas limit 10000002,10; 29.032s
   select id from ipdatas limit 20000002,10; 24.594s
   select id from ipdatas limit 30000002,10; 24.812s 
   select id from ipdatas limit 40000002,10; 28.750s  84.719s
   select id from ipdatas limit 50000002,10; 30.797s  108.042s
   select id from ipdatas limit 60000002,10; 133.012s  122.328s

   select * from ipdatas limit 10000002,10; 27.328s
   select * from ipdatas limit 20000002,10; 15.188s
   select * from ipdatas limit 30000002,10; 45.218s
   select * from ipdatas limit 40000002,10; 49.250s   50.531s
   select * from ipdatas limit 50000002,10; 73.297s   56.781s
   select * from ipdatas limit 60000002,10; 67.891s   75.141s

   select id from ipdatas order by id asc limit 10000002,10; 29.438s
   select id from ipdatas order by id asc limit 20000002,10; 24.719s
   select id from ipdatas order by id asc limit 30000002,10; 25.969s
   select id from ipdatas order by id asc limit 40000002,10; 29.860d
   select id from ipdatas order by id asc limit 50000002,10; 32.844s
   select id from ipdatas order by id asc limit 60000002,10; 34.047s

   至于SELECT * ipdatas order by id asc 就不测试了 大概都在十几分钟左右
   可见通过SELECT id 不带排序的情况下差距不太大,加了排序差距巨大
   下面看看这条语句
   SELECT * FROM ipdatas WHERE id IN (10000,100000,500000,1000000,5000000,10000000,2000000,30000000,40000000,50000000,60000000,67015297);
   耗时0.094ms
   可见in在id上面的查询可以忽略不计毕竟是6000多万条记录,所以为什么很多lucene或solr搜索都返回id进行数据库重新获得数据就是因为这个,当然lucene/solr+mysql是一个不错的解决办法这个非常适合前端搜索技术,比如前端的分页搜索通过这个可以得到非常好的性能.还可以支持很好的分组搜索结果集,然后通过id获得数据记录的真实数据来显示效果真的不错,别说是千万级别就是上亿也没有问题,真是吐血推荐啊.

 

上面的内容还没有进行有条件的查询仅仅是一些关于orderby和limit的测试,请关注我的下一篇文件对于条件查询的1亿数据检索测试

分享到:
评论

相关推荐

    Mysql千万级别数据优化方案

    "Mysql千万级别数据优化方案" 一、 目的与意义 在 MySql 单表中数据达到千万级别时,数据的分页查询结果时间过长,对此进行优达到最优效果,也就是时间最短。为了解决这个问题,我们需要了解 MySQL 数据库的分页...

    Mysql千万级别数据优化方案总结.pdf

    "Mysql 千万级别数据优化方案总结" 在 MySQL 中,当单表中的数据达到千万级别时,数据的分页查询结果时间可能会变得很长。为解决这个问题,我们需要采取相应的优化措施,以达到最短的时间。 建立索引 建立索引是...

    MySQL百万级数据量分页查询方法及其优化建议

    在MySQL中,面对百万级数据量的分页查询,如何高效地进行操作并优化查询性能是数据库管理员和开发人员必须关注的问题。以下是一些常用的方法和优化建议: 1. **直接使用LIMIT语句**:这是最基础的分页查询方式,如`...

    百万级数据库记录下的Mysql快速分页优化实例

    本文档将详细探讨当面对百万乃至千万级别数据记录时,如何优化MySQL的分页查询性能。通过一系列实践案例和深入分析,我们将了解到在不同场景下优化MySQL分页查询的有效方法。 #### MySQL性能瓶颈分析 在进行大规模...

    关于JDBC数据分页跨数据库小结.pdf

    本文主要探讨了如何使用JDBC(Java Database Connectivity)在不同类型的数据库中实现数据分页,包括Oracle、MySQL和ACCESS。数据分页是提高用户界面性能和用户体验的关键,因为它允许用户逐步加载大量数据,而不是...

    c#大数据量分页 大型数据分页程序

    通过对数据库设计、查询优化以及C#代码的合理编写,可以有效地处理大规模数据的分页问题。通过分析和学习这个源码,你不仅可以掌握基础的分页技巧,还能深入理解如何在实际项目中应对性能挑战。 最后,记得在实际...

    mysql入门的资料ppt

    MySQL的主要组件包括Server层、存储引擎层、连接管理器、安全机制、日志管理和查询优化器等。Server层负责处理客户端请求,进行数据存储和查询。存储引擎层负责数据的存储和管理,包括InnoDB、MyISAM等。连接管理器...

    高性能MySQL(第3版).part2

    7.12.5InnoDB和查询缓存319 7.12.6通用查询缓存优化320 7.12.7查询缓存的替代方案321 7.13总结321 …… 第8章优化服务器设置325 第9章操作系统和硬件优化377 第10章复制433 第11章可扩展的MySQL501 第12章...

    基于ssm+mysql的互助养老系统源码数据库.zip

    开发者需要具备扎实的Java编程基础,熟悉SSM框架的使用,同时了解MySQL数据库的设计与优化,以及Web应用的测试与部署流程。这样的系统不仅能提高养老服务业的效率,也能提升用户体验,为构建和谐的养老环境贡献力量...

    mybatis spring sqlserver mysql

    在IT行业中,数据库管理和数据查询优化是至关重要的环节。MyBatis、Spring和SQL Server、MySQL这四个关键词组合在一起,揭示了一个关于如何在Java后端开发中,利用这些技术实现高效分页查询的实践场景。这里我们将...

    教务系统数据库设计

    - 分页查询:对于大量数据,使用LIMIT和OFFSET进行分页,避免一次性加载所有数据。 6. 安全性与性能考虑: - 参数化查询:防止SQL注入攻击,提高代码安全性。 - 数据库连接池:如C3P0或HikariCP,提高数据库连接...

    Spring+mybatis+PageHelper分页插件

    在实际开发中,使用Spring Boot可以快速搭建后端服务,MyBatis作为数据访问层,处理数据库交互,PageHelper则进一步优化了分页操作。在Ajax请求中,由于浏览器的安全策略,不同源的请求会被阻止,因此需要在Spring ...

    bbs论坛 java mysql

    5. **MySQL数据库**:MySQL是一个流行的开源关系型数据库管理系统,用于存储和检索论坛的数据,如用户信息、帖子、回帖等。在设计数据库时,我们需要考虑表的结构、索引优化以及事务处理等。 6. **用户注册与登录**...

    分页助手使用demo

    在IT行业中,分页是数据查询中非常常见且重要的一个功能,特别是在大数据量的场景下,它可以有效地提高用户体验,避免一次性加载过多数据导致的页面响应慢或者内存压力过大。SpringBoot是一个广泛使用的Java开发框架...

    分页效果还行

    控制器可能需要查询数据库并应用分页条件,返回包含当前页数据的模型。 4. **查询优化**:在实现分页时,应考虑SQL查询的优化。使用`OFFSET/FETCH`(SQL Server)或`LIMIT/OFFSET`(MySQL)等SQL语句来限制返回的...

    MySQL提高分页效率

    此外,还可以通过以下方式优化分页查询: 1. **使用索引**:对分页所依赖的排序字段建立索引,可以显著提升查询速度。 2. **避免全表扫描**:利用索引减少扫描行数,尤其是在有复合索引时。 3. **优化查询语句**:...

    省市联动php mysql ajax

    6. 测试和优化:确保在不同浏览器和设备上功能正常,优化加载速度和用户体验。 在实际开发中,还可以考虑使用缓存策略来提高性能,如将常访问的省市县数据缓存在内存中,避免频繁查询数据库。此外,对于大型项目,...

    [[高性能MySQL(第3版)].Baron.Scbwartz等.扫描版

    该书深入浅出地介绍了MySQL数据库的各种优化方法和技术,帮助读者理解和掌握如何构建和维护高性能的MySQL系统。自出版以来,本书因其全面性和实用性而备受好评,成为MySQL领域内不可或缺的经典参考书籍之一。 #### ...

    查询增强功能代码实现与部署

    在IT行业中,查询增强功能是提高数据库操作效率和数据检索精度的重要手段,尤其在大数据量的应用场景下,这种功能显得尤为关键。本文将详细介绍查询增强功能的代码实现及其部署过程,帮助开发者理解如何优化查询逻辑...

Global site tag (gtag.js) - Google Analytics