mysqlinnodbcount(distinct)很慢,怎么优化?
1. 把你的day字段类型改为long型,在页面显示的时候在格式化成自己需要的样式;
2. 在day字段上建立索引;
3. 把ip_4表类型有InnoDB改为MyISAM,如果不需要事物支持的话,建议不要使用InnoDB。
Mysql某个表有近千万数据,CRUD比较慢,该如何优化呢?
MySQL 数据库某张表近千万的数据,CRUD比较慢,如何优化?最常见的是线程池优化、索引优化、缓存优化、读写分离、数据库拆分等,上述4种优化可以从不同角度来优化我们的数据库操作,其中的可操作性性要看团队的技术能力和应用的维护能力,我就以自己遇到过的应用场景简单谈谈自己的优化流程。
换到新的团队,遇到的第一个棘手问题就是数据库不定时的出现“Cannot get a connection, pool error Timeout waiting for idle object”,经和DBA沟通,其反馈数据库group(数据库量级4kw+)中的查询逻辑很多,qps达1w+,并且慢sql积压,拖垮了数据库。从慢sql和上述查询异常着手,进行千万级的数据库优化。
1. 线程池优化。线上的读线程池16,写线程池池16,考虑到数据查询时获取不到数据库连接,将读线程池调整为32,其优化效果不明显,数据库建立连接的异常仍然存在。
2.索引优化。经和DBA分析相关的慢sql语句,发现其索引都是完备的,也就是说每个查询都可以落到对应的索引逻辑,这点儿我们心里是有数的,毕竟线上正常运行了2年多数据库,当时建库和查询时肯定考虑到了索引的情况。也就是说,在这方面没有优化的余地。
3.缓存优化。经排查,线上的相关操作采用缓存加速,缓存时间1h或24h不等,考虑到数据库瓶颈和更新数据删缓存的逻辑,将缓存时间延长至7天。该优化逻辑上线后,数据库异常有所减弱,但问题仍未解决。偶尔发现,客户端偶尔会请求服务端不存在的数据,引发缓存穿透。而针对该库涉及到的可能存在缓存穿透的逻辑,进行了一系列优化。优化之后,效果特别明显,也就是在线上业务达到一定量级时,要特别注意缓存穿透,这点在业务刚开始时很容易被忽略。
4.读写分离。虽然通过缓存穿透的优化处理,解决了数据库连接异常的问题,但是读写分离仍然值得尝试,读写分离是应对读多写少业务的一大利器,一主多从的读写分离模式被引入弹性数据库体系,让我们在特殊节点的业务保障更有信心。
5.数据库拆分,也就是分库分表。业务发展到一定程度,分库分表是优化的必经之路,也是我们团队一项很重要的优化业务,但限于业务场景、分库分表规则、多维度查询、团队研发资源等,目前正在规划中。
综上所述,通过优化缓存穿透和读写分离解决了我们线上业务的数据库性能问题,可操作性强,风险相对降低。
作者:夕阳雨晴,欢迎关注我的头条号:偶尔美文,主流Java,为你讲述不一样的码农生活。
这个数据量,建索引,会影响插入更新的性能。遇到复杂多变的业务场景,那么多的索引是很恐惧的。
减少数据量,只有分库分表,提高插入速度。
但是分库分表,会给正常的查询带来影响,也就是老的代码要重构了,还要考虑主键的生成。
如果业务简单,建议加索引,读写分离,加缓存解决。
如果业务复杂,还是直接上elasticsearch把。
crud慢。。。insert慢你就分区,不影响业务分表分实例也行;update delete看你什么模式了,如果是大数据量带复杂条件的跟select一样分析访问路径,总之先分析,别盲目的上方案,我见过更新数据花四十多分钟,开发一群人讨论分库分表,后来调整了index变成四分钟的,凡事都先分析一下,虽说工程师不是科学家,但是也别太无脑
调整mysql配置参数
若是读为主,可以考虑打开query_cache,以及调整一些参数值:sort_buffer_size,read_buffer_size,read_rnd_buffer_size,join_buffer_size
优化索引
对出现在where子句中的字段加索引, 全表扫描的性能通常是很差的,要尽量避免。
组合索引和覆盖索引
硬件升级
更多的内存和更快的硬盘。如果是InnoDB引擎,多利用点内存,减轻磁盘IO负载,因为IO往往是数据库服务器的瓶颈;
分区分表
mysql自带分区表,对应用是透明的,无需更改代码, 但是sql语句是需要针对分区表做优化的,sql的where条件中要带上分区条件的列,从而使查询定位到少量的分区上,否则就会扫描全部分区
分表和分区的思路是差不多的,都是将查询固定到一个范围,降低数据读取量,相对分区来说,分表不需要知道分区字段,但是需要知道分表规则。就导致需要修改现有代码来适配现有的分表逻辑,而且当数据量增加的时候,分表数量会一直递增,导致后期数据处理困难。
读写分离
主从复制,对主库进行CUD,对从库进行R,保证R不会受到CUD的影响,保证了查询性能,可以在应用层修改,也可以用第三方工具。
由于Mysql主从复制是异步的,主从在同一时刻难免存在数据不一致的问题,特别是主从机器是跨机房或者跨地域,网络延迟大,数据很难保持强一致性。所以若是要求数据强一致性,这种方法就不合适
crud同时在一张表上并发进行,由于事务的隔离性,当表中数据很大时是肯定不行的。
有人说使用读写分离,但对于写来讲,多个并发事务对同一张大表执行并发的事务性操作也会对性能造成极大影响。
还有人说表分区,横向分区只是减少了事务性操作的数据规模,把对一个数据集的操作分摊到多个数据集而已,对于千万甚至上亿数量级而言效果并不明显。
可以考虑使用事件溯源(Event Souring)+读写分离(CQRS)相结合的方法。事件溯源保证了只执行插入操作,而且插入的并不是数据本身,而是在事件表中插入新增数据的事件event,数据是以这个事件的属性保存的。对数据的修改和删除也同样是以事件形式插入事件表,这种只插入不修改或删除保证了极其强大的时间性能。如果我们想获取某一时刻的数据历史值,则把这个数据从它的起始时刻到特定时刻之间的所有事件回放一遍,即可获得当时的数据值。为了事件表本身的规模不至于太大,我们还可以定期生成它的快照,将在此之前的所有事件应用回放从而获得每个数据的现场值并压缩了事件表。
除了事件溯源以外,我们还应该使用数据库提供的数据复制功能(所有关系型数据库都提供,例如mysql和mariadb的binlog)或使用第三方组件(例如阿里云的canal)将事件实时复制到其他数据库中,从而实现读写分离。这时也可以使用eventuate事件溯源框架,并结合kafka或rabbitmq作它的事件消息总线。在用于读的数据库中我们一般使用物化视图,也就是说,把接收到的事件直接应用在物化视图上,最终用户看到的是物化视图中的统计分析数据。
mysql数据库设计与优化,应不应该使用约束?
首先使用约束可以确保表数据的准确完整和唯一性;
其中常见的约束有
PRIMARY KEY, DEFAULT, UNIQUE, FOREIGN KEY,NOT NULL
一般情况下:DEFAULT 和 NOT NULL是会限制的,可以确保数据完整避免程序逻辑不够严谨造成的系统异常。但也不是绝对的,如果是后期优化还要考虑现有数据是否会造成冲突。
PRIMARY KEY 在大对数情况下会设置作为业务数据的唯一标识符。但一些关系表一般可以不设置。有人说PRIMARY KEY 必须自增,其实也未必。得就实际业务需求而定。
UNIQUE 约束可以保证一列或者多列组合值都是唯一的。可以提升这一列的搜索效率。但同样也得考虑历史数据的情况。
当然以上情况只是经验之谈,具体数据库的优化一定是根据实际的业务逻辑进行的。可能没有什么必须遵守不可违背的定律。
只要符合业务需求并且能够提升业务效率,就是合理的设计。
外键约束可以保证数据的正确性和有效性,防止出现不符合预期数据,从数据的角度来说是必要的。为了保证约束,数据库会在更新数据时,对相应表的数据进行检查,这就带来了很大的性能开销。
目前的互联网应用实践来说,一般在开发测试环境使用外键,而生产环境则不使用外键。目的是在开发测试阶段通过数据库的外键机制来验证程序的正确性,而在生产环境则不使用外键,来提升数据库的性能。
非空约束推荐使用,以mysql来说,是有好处的。
如果一个字段它的数据要求每一行数据都是唯一,并且会频繁用于查询,那么推荐增加唯一索引
这是一项新功能,用于指定在插入或更新到一行之前检查值的条件。如果表的任何行的搜索条件的结果为 FALSE,则约束可能返回错误(但如果结果为 UNKNOWN 或 TRUE,则约束不会返回错误)。此功能开始在 MySQL 8.0.16 上运行,在以前的版本中,我们可以创建它,但它不起作用,这意味着支持语法,但不起作用。要牢记的使用规则:
- AUTO_INCREMENT 自增列不允许使用
- 引用另一个表中的另一列不允许使用
- 存储的函数和用户定义的函数不允许使用
- 存储过程和函数参数不允许使用
- 子查询不允许使用
- 在外键中用于后续操作(ON UPDATE,ON DELETE)的列不允许使用
- 为下一条语句 INSERT,UPDATE,REPLACE,LOAD DATA 和 LOAD XML 评估此次监测。此外,还会为 INSERT IGNORE,UPDATE IGNORE,LOAD DATA…IGNORE 和 LOAD XML…IGNORE 评估此监测约束。对于这些语句,如果约束的评估结果为 FALSE,则会发生警告。插入或更新被跳过。
我们可以使用此功能在表中添加更多的逻辑,但是根据我以前作为程序员的经验,我不建议在表中添加逻辑,因为除非您无法访问应用程序代码,否则很难找到或调试错误。