问题反馈:PostgreSQL分页异步查询分区表当查询结果大于1.5W行时前N页加载很慢 返回

SqlSugar版本:SqlSugarCore 5.1.3.30
数据库:PostgreSQL 9
C# .net6 web站点
问题描述:这是一个很神奇的现象,每天新增的记录数大约在(2-3万行之间),直接执行SQL无延时卡顿现象,分页异步查询分区表当查询结果大于1.5W行时前N页加载很慢,且分2种情况
1、默认查询当天数据,当查询结果行数不多时响应时间正常,大于1.5万行时开始第1页卡,数量越多从第1页起卡的页数越多,如:超过2万行时,前5页卡,页码大于5就不卡了。
2、改变条件查今天之前的历史数据时(查一天的),第一次打开页面时至少卡10秒以上,数据加载完成后,再次刷新或翻页响应效率为第1种情况。
PostgreSQL分区表,结构如下
1 2 3 4 5 6 7 8 9 10 11 | CREATE TABLE IF NOT EXISTS x_record ( id serial8 NOT NULL , add_time timestamptz, --此处省略6个integer,1个varcahr,13个bigint,1个timestamptz ) PARTITION BY RANGE (add_time); CREATE TABLE x_record_202308 PARTITION OF x_record FOR VALUES FROM ( '2023-08-01 00:00:00+08' ) TO ( '2023-09-01 00:00:00+08' ); CREATE INDEX IF NOT EXISTS x_record_202308_idx_add_time ON x_record_202308(add_time); CREATE INDEX IF NOT EXISTS x_record_202308_idx_id ON x_record_202308(id); |
以下为C#查询代码,查询时间范围1天,每页20行
1 2 3 4 5 6 7 8 9 10 11 12 13 | var exp = Expressionable.Create<x_record>() .And(a => SqlFunc.Between(a.add_time, fromTime, toTime)) .ToExpression(); var list = await db.Queryable<x_record>() .Where(eWhere) .OrderBy(a => a.id, OrderByType.Desc) .Select(a => new x_view() { id = a.id , add_time = a.add_time, //省略部分字段 }).ToPageListAsync(page, 20); |
解决方法:改用直接执行SQL再绑定就很丝滑了
1 2 3 4 5 6 7 8 9 10 11 | string tmpSql = db.Queryable<x_record>() .Where(eWhere) .OrderBy(a => a.id, OrderByType.Desc) .Select(a => new x_view() { id = a.id , add_time = a.add_time, //省略部分字段 }).ToSqlString(); var list = await db.Ado.SqlQueryAsync<x_view>(tmpSql + $ "limit 20 offset {((page - 1) * 20)};" ); |
热忱回答(20)
-
fate sta VIP0
2023/8/7-
0 回复 -
fate sta VIP0
2023/8/7-
0 回复 -
fate sta VIP0
2023/8/7你都分页了怎么会慢呢?
0 回复 -
fate sta VIP0
2023/8/7你看看是不是条件引起的
0 回复 -
fate sta VIP0
2023/8/7这个速度应该是sql快慢,ToListAsync底层就是 db.Ado.SqlQueryAsync
0 回复 -
fate sta VIP0
2023/8/7db.Queryable<Order>().Skip(1).Take(200).ToSqlString()
比较一下SQL
0 回复 -
道念迹奇 VIP0
2023/8/8@fate sta:对比了一下,SQL语句结构是一样的
之所以说诡异是指分页时在前N页会卡顿,结果越多,N值会变大,超过页码分界线往后效率就正常了
0 回复 -
道念迹奇 VIP0
2023/8/8@fate sta:刚才我重新写了查询案例:2种写法的效率是不一样的
1、前N页卡顿的写法
1db.xxxx.ToPageListAsync(page, limit);
查询20页时间:
total:16433,page:1,耗时:2309.9048
total:16433,page:2,耗时:1553.7535
total:16433,page:3,耗时:1581.5697
total:16433,page:4,耗时:1549.5327
total:16433,page:5,耗时:1652.3516
total:16433,page:6,耗时:1614.657
total:16433,page:7,耗时:1571.5268
total:16433,page:8,耗时:1686.1091
total:16433,page:9,耗时:1768.5345
total:16433,page:10,耗时:1660.1226
total:16433,page:11,耗时:1740.2945
total:16433,page:12,耗时:1710.5694
total:16433,page:13,耗时:1779.3872
total:16433,page:14,耗时:1822.8966
total:16433,page:15,耗时:1641.3461
total:16433,page:16,耗时:1554.6926
total:16433,page:17,耗时:1823.3728
total:16433,page:18,耗时:79.5095
total:16433,page:19,耗时:71.8547
total:16433,page:20,耗时:59.9317
2、以下写法效率正常
1db.xxxxx.Skip((page - 1) * limit).Take(limit).ToListAsync();
查询20页时间:
total:16433,page:1,耗时:585.4071
total:16433,page:2,耗时:67.9149
total:16433,page:3,耗时:64.731
total:16433,page:4,耗时:72.2917
total:16433,page:5,耗时:110.8405
total:16433,page:6,耗时:78.7364
total:16433,page:7,耗时:88.1795
total:16433,page:8,耗时:92.128
total:16433,page:9,耗时:97.117
total:16433,page:10,耗时:99.5275
total:16433,page:11,耗时:105.6536
total:16433,page:12,耗时:130.1762
total:16433,page:13,耗时:129.8083
total:16433,page:14,耗时:214.9252
total:16433,page:15,耗时:183.8991
total:16433,page:16,耗时:108.8862
total:16433,page:17,耗时:100.3811
total:16433,page:18,耗时:253.7756
total:16433,page:19,耗时:166.4153
total:16433,page:20,耗时:177.1487
0 回复 -
道念迹奇 VIP0
2023/8/8升级到:5.1.4.95版问题依然存在
0 回复 -
fate sta VIP0
2023/8/8你是不是有查询count, Count会影响性能的
0 回复 -
fate sta VIP0
2023/8/8如果还有问题 按模版提供DEMO
https://www.donet5.com/Home/Doc?typeId=2366
0 回复 -
fate sta VIP0
2023/8/8db.xxxxx.Skip((page - 1) * limit).Take(limit).ToListAsync();
在不查Count情况下等于
ToPageLis 底层是一模一样的没有任何差异的地方
0 回复 -
fate sta VIP0
2023/8/8数据量过大不要查询Count这个比较慢
0 回复 -
道念迹奇 VIP0
2023/8/9@fate sta:剔除Count效率一样的不行,确定是ToPageList这个用法导致的效率问题,是否返回count问题都在,同步异步都有的,刚才还试了普通表,也有一样的情况。
可能跟字段数量多少也有关系,同样的表结构复制4个字段没复现,有时间我整理复现列子
0 回复 -
道念迹奇 VIP0
2023/9/19不好意思最近有点忙,就没做案例,并且无意间找到为啥直接执行SQL不卡的原因了,分区表查询的时候,《分区键》作为查询条件时使用传参方式查询时无法触发《分区约束排除》导致查询所有子表导致效率极低,而直接使用SQL不会有这个问题
0 回复 -
fate sta VIP0
2023/9/19@道念迹奇:参数方式如果dbtype都一样也无触发是吗?
0 回复 -
fate sta VIP0
2023/9/19如果这样那就不是sqlsugar的问题了
0 回复 -
fate sta VIP0
2023/9/19dbtype不一样引起的慢可以看一下 文档:字符索引优化
0 回复 -
道念迹奇 VIP0
2023/9/20@fate sta:对的不是sqlsugar的问题
0 回复 -
道念迹奇 VIP0
2023/9/20@fate sta:不是索引问题,是PG分区表有个《分区约束排除》机制没触发导致的,《分区键》只能用具体值查询时才能触发定位对应子表,用内置函数、参数都无法触发
0 回复