{eval=Array;=+count(Array);}

问答专栏Q & A COLUMN

mysql数据表规模九千万左右,怎么优化查询?

olleolle 回答0 收藏1
收藏问题

10条回答

elisa.yang

elisa.yang

回答于2022-06-28 14:38

我的天啦,一个表九千万也是了不得了!

我上家公司明确规定,一张表不能超过5000万,因为查询效率会有更大的降低!

无论如何,看下如何优化数据查询吧!

①,单库单表:

1,加索引,一个好的索引能用空间换取查询时间的大为降低!

2,使用存储过程:减少sql编译的时间!

3,优化sql:包括联合查询的指向,where,order语句使用索引字段,减少使用多表联合查询,不要使用select *等等!

4,参数配置:扩大内存,调节线程池参数等等!

5,开启缓存:开启二级缓存,三级缓存,提升查询效率!

②,单库多表:

使用水平拆分(比如按月份),将表分为12张表,然后在代码端按照月份访问相应月份的表!

使用垂直拆分:很多字段只是作为保存记录用,(像一些约定,备注啥的字段往往很大),可以将查询中常常用到的字段放在常用的一张表中做查询,另一些字段放另一张表中存储,通过某个唯一索引字段联系起来,可以保证查询效率大为提升(因为磁盘IO减少)!

③,多库多表:

①,主从读写分离:表中数据虽然还是一致,但是由于多个从库读,主库写数据,大大减少共享锁的性能开销!

②,分库分表:指定一个字段作为,分库字段,利用hash值或者其它策略,分布在不同的库里面,在按照相应分布策略(比如上面的水平拆分或者垂直拆分),分散到不同的表里!

比如我们现在的数据库设计为8库1024表,你的将近一亿的数据在我们的单张表里面只有不到10W!

虽然理论上,一张表的大小不做任何限制,但是基于查询效率,索引性能等,不宜超出5000万数据!

关于多线程,分布式,微服务,数据库,缓存的更多干货,会继续分享,敬请关注。。

评论0 赞同0
  •  加载中...
HollisChuang

HollisChuang

回答于2022-06-28 14:38

实践出真知。根据成本顺序依次是:

第一:加索引优化sql。尽量避免全盘扫描,另单表索引也不是越多越好。

第二:加缓存。使用redis,memcached,但注意缓存同步更新、设置失效等问题。

第三:主从复制,读写分离。适合读多写少的场景,同步会有延迟。

第四:垂直拆分。可以选用适当的中间件Mycat等

第五:水平切分。选择合理的sharding key,改动表结构,将大数据字段拆分出去,对经常查询的字段做一定的冗余,同时做好数据同步。

当然还有优化数据库连接配置,根据业务选用不同的数据库引擎等等。

我是一名架构师,欢迎关注,给技术加点料

评论0 赞同0
  •  加载中...
孙淑建

孙淑建

回答于2022-06-28 14:38

我不清楚答题的大部分人是否有真正实践过,特别是用mysql实践过。大部分说是加索引、调整参数不是说不正确,有效果,但是不能很好的解决问题。说说个人想法:


部分答主的方案的确不敢苟同,纠正如下:

1、select count(*) 和 select count(主键) 在现阶段的mysql 没有太大区别,新版mysql这个对性能影响可以忽略。

2、强烈反对使用存储过程,后面介绍了使用分表分库的方案,就更不要用存储过程了。

3、单表行数和表数量,需要找到平衡点。表太多,性能也会下降。


我的回答:

1、单表9000w数据,mysql存储不了,想办法分表分库。500w数据的时候,你就该有这个想法了。只加索引解决不了问题,9000w的单表数据,很难平衡查找和插入性能,索引稍微多了插入性能也很低。

2、不要再说select count了,放弃汇总查询的想法,根本查不了。

3、数据最终以mysql作为主要存储,考虑最终查询的数据源放在非关系的数据存储上,mongo,es都可以考虑下。

4、业务场景都是需要实时查询9000w数据吗?非实时数据,可以考虑hadoop系大数据方案。

5、最后说下,mysql 和oracle,sql server不一样,不一样。

评论0 赞同0
  •  加载中...
Bryan

Bryan

回答于2022-06-28 14:38

是一张表九千万了吗?

建议:

第一、表读居多还是写?读的话数据库引擎用myisam ,写的话InnoDB 而不是MyISAM,因为MyISAM有太多锁。

第二、升级到MySQL 5.5 ,确保使用buffering功能。

第三,索引确保使用正确,且都在内存中,移除没有必要的索引。

第四、写场景多吗? 设置innodb_buffer_pool_size足够大来确保更快的写操作。

第五、按业务id取模,分表。

最后,花钱加机器内存和用ssd磁盘吧。

评论0 赞同0
  •  加载中...
AJie

AJie

回答于2022-06-28 14:38

作为一个多年的WEB后端程序员,经常与各种数据库打交道,下面分享一些自己的处理方式给你。

对于数据量这么大的数据,MySQL提供了以下优化方案:

1.常规方式索引,这里需要注意的是,索引也是一种文件,如果你的服务器或者数据库内存非常小,一次无法将所有的索引文件载入,这个时候索引文件因为要反复在磁盘和内存之间进行切换,这样效果肯定非常不明显,导致查询也变慢,所以这种情况可以适当增加内存,以满足索引文件一次载入到内存进行检索查询。

2.表分区保存,对于这么大的数据,可以根据具体的需求进行表分区保存,在进行表分区保存的时候,需要注意,一定要根据具体的需求进行分区,这和建立索引是一样的道理。

3.用程序实现分表保存,比如在保存和查询数据的时候,生成主键时,可以用某种规则将其保存在90个表左右,这样就变成了90个100万数据的表,查询肯定会提升,不过对于分表保存,目前MySQL数据库对于INNODB存储引擎没有提供太多的支持,所以这一切必须由我们自己写程序来实现。

如果你还有什么问题,可以在评论中留言。

评论0 赞同0
  •  加载中...
Richard_Gao

Richard_Gao

回答于2022-06-28 14:38

读写分离,分库分表,热数据放内存。

读写分离:减少写库所带来的行锁甚至表锁对查询的影响,提升查询效率,同时还可以保证高可用。

在设计系统之初就设计好垂直分库和垂直分表,比如垂直分表:在一张大表中,一些热数据的字段放在一起,一些不常用的而且占用空间比较大的字段放在另外一张表,这样子做的好处是提升了查询速度,因为mysql是以页存储数据的,一页之中存放的数据越多,查询效率会更高。

另外再配合redis mongodb这些缓存数据库,热数据放进去,查询效率会进一步得到提升。

如果上面的方案还无法解决查询缓慢的问题,可能是因为我们的数据量非常大,而且持续快速增长。我们还可以进行水平分库分表,例如把一张1亿数据量的大表,水平拆分成10张相同的大表,再水平拆分到10个不同的数据库中。。。

觉得可以的点个赞

评论0 赞同0
  •  加载中...
RyanQ

RyanQ

回答于2022-06-28 14:38

9千万的数据,如果现在基本不再增长,可以优化一下,首先找到性能问题的原因,是sql的问题,还是设计的问题。为了提高查询效率,在设计上可以采用非常规设计,比如反范式设计等。或者把join的表拆开。方法很多,只能根据具体业务来说,你可以把现在的查询语句列出来,具体分析。9千万数据,如果根据主键id查询,那也能在100ms内查询出来结果。


如果现在每天还有不少增量数据,分表就不可避免了。就是把一个表的数据分成多个表,这个还是得 根据业务类型来确定,按照时间来分表?还是按照id来分?这个得具体分析。分库分表带来的 改动相对较大。

评论0 赞同0
  •  加载中...
jonh_felix

jonh_felix

回答于2022-06-28 14:38

最简单的方法就是优化查询,第一点,可以建立索引,因为索引可以很大程度优化查询。第二点,可以配置缓存还可以用slow_query_log进行分析,这样很大提升查询的。第三点,建立分库分表,因为分库分表是查询的杀手锏。第四点,优化sql语句,比如子查询的优化等。第五点,就是在连表查询是要使用Join表的时候使用相当类型的例,并将其为索引。

评论0 赞同0
  •  加载中...
Shihira

Shihira

回答于2022-06-28 14:38

9000万的话,如果前端访问量不是过大,单机就可以优化


数据库优化

  • 结合slow query,用explain进行sql优化,包括优化索引等优化。只有最慢的几条sql优化好了,瞬间整个mysql都畅快了
  • 分表,根据一定的条件进行分表,比如按照时间或者冷热数据或者hash区分
  • 不能分表,就加点内存,调一下mysql的缓存参数
  • 读写分离,以这个数据量场景如果数据量增长不大,前端访问不频繁,就没必要读写分离,做分表就ok

应用层优化

  • 原则就是优化slow query排前的,还有就是量大排前的,通过应用层代码替代数据访问减少对数据库的压力和访问量
  • 增加缓存,比如程序自身开设缓存或者redis等专门缓存服务器
  • 优化sql,尤其是关联查询,都要避免掉,改成n+1查询,让n都能命中缓存
  • 高频sql尽量优化成可以走缓存
  • 针对分表要做dao层改进
  • 如果数据库读写分离,这边也需要修改

评论0 赞同0
  •  加载中...
glumes

glumes

回答于2022-06-28 14:38

首先应该看你们是什么业务,针对业务类型的不同可以采取不同的优化方式。

1.如果是线上环境,对外提供服务,这个表确实是很大了,无论索引设计的多么合理,进行查询和插入的时候都会耗时较长,性能低下。特别是遇到连表查询的时候,会更慢。这个时候可以考虑进行分表或者分区表。

1.1分表:是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,我们可以称为子表。app读写的时候需要先根据事先定义好的规则得到对应的子表名。

1.2分区表:和分表相似,都是按照规则分解表。不同在于分表将大表分解为若干个独立的实体表,而分区是将数据分段划分在多个位置存放,可以是同一块磁盘也可以在不同的机器。分区后,表面上还是一张表,但数据散列到多个位置了。app读写的时候操作的还是大表名字,这种方式对程序来说是透明的,无需更改程序。不过要注意sql查询的时候需要加上可以定位到某个分区表的条件,否则会是整个大表扫描,性能比未分区前更慢。

分区的类型有:

RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。

LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。

HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。

KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。

除了分表和分区表外,还可以采取缓存,redis或者mamecache,降低mysql数据库的压力。

2.如果是统计业务,则可以采取别的数据库存储数据,像是列数据库,mariadb columnstore ,计算能力比myslq强大很多。

评论0 赞同0
  •  加载中...

最新活动

您已邀请0人回答 查看邀请

我的邀请列表

  • 擅长该话题
  • 回答过该话题
  • 我关注的人
向帮助了您的网友说句感谢的话吧!
付费偷看金额在0.1-10元之间
<