添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
闷骚的蛋挞  ·  学术交流 | ...·  1 月前    · 
含蓄的莲藕  ·  解决%matplotlib ...·  9 月前    · 

数据库用的是pgsql。sql 中用到了表连接,group by ,count以及sum 函数,现场测试的时候由于有定时任务在跑,所以数据库中一直有增量。当数据达到200万条时,页面加载时间非常慢,达到40s。

问题分析过程

本人开发小白一个,日常搬砖。之前没有接触过太大数据量的业务,只有面试的时候自己看过相关的sql优化知识,而实践还是头一次。
1.把查询慢的sql提出来,对where条件中的字段加上索引。由于之前开发用的是mysql,对pgsql 的一些特性不是很了解,所以默认的索引结构都是btree。

CREATE INDEX indexname ON tablename (code)
select
          count(retrival.id) retrivalNum,
          retrival.index_code,
          retrival.camera_name,
          province."name" place,
          sum(end_time-start_time) retrivalDuration,
          retrival.province_code
           retrival
        left join
           resource
          retrival.index_code = resource.index_code
        left join
          province
          resource.province_code  = province.code    
         group by
        retrival.index_code,resource.province_code,retrival.camera_name

2.由于业务比较复杂,涉及到了三个表关联,后来和对接人探讨,最后决定在表中加一个关联字段,以达到少关联一个表的目的。

select
          count(retrival.id) retrivalNum,
          retrival.index_code,
          retrival.camera_name,
          province."name" place,
          sum(end_time-start_time) retrivalDuration,
          retrival.province_code
          retrival
        left join
           province
          retrival.province_code  = province.code
        where position('100000' in province.path) > 0
        and retrival.camera_name like '%%'
        AND retrival.start_time >= ''
        AND retrival.end_time <=  ''
        group by
        retrival.index_code,retrival.province_code,retrival.camera_name,province.name
        limit 25 index 0

3.对连接表关联到的字段加索引。
4.加完索引之后查询时间并没有得到改善,查询时间还是30s左右,加上分页并没有什么大的影响。
5.这时候我想着尝试不做表关联,将sql拆分,去掉group by ,将逻辑转换到代码中(以为这样会更快)
改完之后测试接口请求,发现在代码中效率也没有得到改善,反而更慢,因为放到代码中分页的优势就没有了。
6.由于项目现场催的比较紧,没有足够的时间去查阅相关资料,所以求助了带我的导师。
7.导师将字段索引分类改成了联合索引,并根据不同的查询条件修改对应的索引结构。这里pgsql 不只有btree一种索引结构。还有brin,gin等,初步了解gin可用到模糊查询(适用于非前缀模糊查询)的字段,brin 是比较,类似于>= <=等。

create extension pg_trgm; 
create extension btree_gin; (必须管理员权限执行)
create index indexname on tablename using gin (...)
create index indexname on tablename using brin (...) with (pages_per_range=1)	

8.修改联合索引并调整字段顺序之查询时间在15s左右。explain 看sql 执行情况,发现还是group by 上面以及count 函数消耗的时间比较久。group by 后面跟了四个字段。这时候数据量已经达到700万。所以还是需要再优化。
9.导师提出了pgsql 的with 语句,此处,将group by 拆分,在with 中只根据count里面的字段进行统计,此处with 相当于将结果放入内存作为一个临时表。然后再从内存中关联其他需要的字段。这样优化之后分页查询执行时间只需要几百毫秒。

WITH tm AS (
	SELECT 
	retrival.index_code,
	COUNT
	( retrival.index_code ) retrivalNum,
	SUM ( end_time - start_time ) retrivalDuration
	retrival
	JOIN province ON retrival.province_code = province.code 
WHERE
	retrival.start_time >= '' 
	AND retrival.end_time <= ''
--	AND retrival.camera_name LIKE'%研%' 
	AND POSITION ( '100000' IN province.PATH ) > 0 
GROUP BY
	retrival.index_code
ORDER BY retrival.index_code
LIMIT 25 OFFSET 0
	SELECT 
	distinct retrival.index_code,
	retrival.province_code ,
	retrival.camera_name,
	province."name" place,
	t.retrivalNum, t.retrivalDuration
	FROM  retrival
	JOIN tm t ON retrival.index_code = t.index_code
	JOIN  province ON retrival.province_code = province.code
	ORDER BY retrival.index_code
	LIMIT 25 OFFSET 0

explain 查看
在这里插入图片描述
可以看到explain查出来的执行计划中都用到了哪些索引,pgsql 默认是按顺序扫描的,用下面的这个语句可以禁用顺序扫描强制使用索引,执行之后速度更快,控制在100ms左右

SET enable_seqscan = OFF;

简单了解用到的pgsql 的索引结构

BRIN索引:存储关于存储在表的连续物理块范围内的值的摘要,可以使用BRIN索引的特定操作符根据索引策略而变化。对于具有线性排序顺序的数据类型,索引数据对应于每个块范围的列中值的最小值和最大值。这支持使用这些运算符的索引查询:

Gin索引是用来加快全文搜索的,适合做模糊查询和正则查询。
btree 和 brin 比较(pgsql 社区有相关演示及介绍):
1.空间上:BRIN相比BTREE索引在空间占用上小很多(数据量千万级时有几千倍之差),在存储空间占用上具备巨大优势。对于数据仓库或者VLDB应用可以节省大量的存储成本。
2.查询上:对于等值的唯一查询,BTREE在性能上有显著优势。但在不同数据分布情况下,BTREE在性能上的领先优势差别非常大,从不到1倍到265倍。
3.在选择创建BRIN还是BTREE索引时,需要权衡性能和空间使用两方面的影响。根据数据量、数据分布和SQL选择最适合的索引类型。在性能相差不大的情况下,选择BRIN可能是更加经济的选择。总体来说,当实际匹配数据量较少时,BTREE索引更加适合;反之,BRIN更加适合。
4.由于BRIN索引的lossy特性,需要消耗较多的CPU时间用于精确匹配。

pgsql 的with

概念:WITH语句通常被称为通用表表达式(Common Table Expressions)或者CTEs。
WITH提供了一种方式来书写在一个大型查询中使用的辅助语句。
可以被看成是定义只在一个查询中存在的临时表。
使用:在WITH子句中的每一个辅助语句可以是一个SELECT、INSERT、UPDATE或DELETE,并且WITH子句本身也可以被附加到一个主语句,主语句也可以是SELECT、INSERT、UPDATE或DELETE。

对于更大数据量的数据还有没有其他更好的方案

查阅了一下网上资料,关于pgsql 大数据量的查询优化文章还是很多的。此处简单罗列,毕竟需要学习和了解的还很多。希望以后能够结合实际业务都能运用的上。
1.根据一定的条件进行分区(年月日等)
2.增加内存大小
3.根据不同的条件合理的时候相应的索引结构。
4.硬件上的优化支持

记一次百万数据量查询sql 优化问题描述问题分析过程总结问题描述数据库用的是pgsql。sql 中用到了表连接,group by ,count以及sum 函数,现场测试的时候由于有定时任务在跑,所以数据库中一直有增量。当数据达到200万条时,页面加载时间非常慢,达到40s。问题分析过程本人开发小白一个,之前没有接触过太大数据量的业务,只有面试的时候自己看过相关的sql优化知识,而实践还是头... CREATE INDEX f_invoice_item_order_item_id_idx ON ins_dw_prd12.f_invoice_item USING btree (order_item_id) CREATE INDEX f_invoice_ite      收到疯狂的慢查询及请求超时报警,通过metrics分析出来自mysql请求的异常,cli —> show proceslist 看到很多慢查询。 先前该sql是没有的,后面因为数据量的增长才出现了这问题。 虽然feeds表大到一个亿,但因为feeds流信息有近期热的特征,所以不是因为 innodb_buffer_pool_size 低效引起的io频繁。 后来经过进一步explain执行计划分析得出了原因,mysql查询优化器选择了他认为高效的索引。 mysql查询优化器大多数情况是靠谱的!  但是你的sql语言含有多个索引时就要注意了,往往最后的结果令人有些彷徨了。因为mys
用php处理百万级以上的数据提高查询速度的方法:  1.应尽避免在 where 子句中使用!=或 2.对查询进行优化,应尽避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。  3.应尽避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:  select id from t where num is nu
这两天,越来越觉得自己做的玩家历史表,查询速度很慢,开始还以为是网络的问题,然后持续了一两天很快pass了这个想法。很可能是自己的查询速度慢,于是进入数据库看了一下,发现历史录已经达到了600多万条了。随着dau的上升,玩家越来越多,乃至于历史录也成倍的增长,虽然自己做了定时删除七天以前的录,但还是承受不住巨的人数增长带来的历史数据剧增。 因此,本人操作数据库直接测试了一下查询历史录的
--查询语句 SELECT * FROM Table_Name1 left join Table_Name2 on columns_name1=columns_name2 WHERE columns_name1=2906332 Table_Name1 、Table_Name2 均为 数据表 ,且数据量都不太小,执行查询特别慢。 --给两张表添加索引 Table_Name1 的...
大数据时代,人们使用数据库系统处理的数据量越来越大,请求越来越复杂,对数据库系统的大数据处理能力和混合负载能力提出更高的要求。PostgreSQL 作为世界上最先进的开源数据库,在大数据处理方面做了很多工作,如并行和分区。 PostgreSQL 从 2016 年发布的 9.6 开始支持并行,在此之前,PostgreSQL 仅能使用一个进程处理用户的请求,无法充分利用资源,亦无法很好地满足大数据、复杂查询下的性能需求。2018 年 10 月发布的 PostgreSQL 11,在并行方面做了大工作,支持了并
Mybatis-Plus分页查询优化主要有以下几点: 1. 使用分页插件:Mybatis-Plus提供了一个分页插件,可以方便地实现分页查询。使用分页插件可以减少代码,提高开发效率。 2. 合理设置分页参数:在进行分页查询时,需要设置分页参数,包括当前页码、每页显示的录数等。合理设置分页参数可以减少查询时间,提高查询效率。 3. 使用缓存:Mybatis-Plus支持缓存功能,可以将查询结果缓存到内存中,下次查询时直接从缓存中获取数据,避免重复查询数据库,提高查询效率。 4. 优化SQL语句:在进行分页查询时,需要编写SQL语句。优化SQL语句可以减少查询时间,提高查询效率。可以使用索引、避免使用子查询等方式优化SQL语句。 5. 分批查询:如果查询结果集非常大,可以考虑分批查询,将查询结果分成多个批次查询,每次查询一部分数据,避免一次查询数据,提高查询效率。