我正在本地主机上运行一个查询,我对SQL非常陌生。我使用一个golang库来生成查询语句。这是一个企业应用程序,所以我没有时间来评估和编码所有可能的性能案例。对于最大可能的查询,我更喜欢良好的性能:
目前,我使用JOIN来查找lat、lng作为记录,以及一些查询参数。我应该以不同的方式加入吗(左,右)?从表是记录还是关系?子查询?
从UI的角度来看,这种查询性能合理吗?这是在本地主机(码头)上的一个相当低性能的笔记本电脑,在WSL (16 on /6核心CPU 2.2GHz)。
-- [2547.438ms] [rows:874731]
SELECT "Longitude","Latitude"
FROM Wells
JOIN Well_Reports ON Well_Reports.Well_ID = Wells.Well_ID
JOIN Lithologies on Lithologies.Well_Report_ID = Well_Reports.Well_Report_ID
where Lithologies.Colour IN
(
'NULL',
'Gray','White','Dark','Black','Dark Gray','Dark Brown','Dark Red','Dark Blue',
'Dark Green','Dark Yellow','Bluish Green','Brownish Gray','Brownish Green','Brownish Yellow',
'Light','Light Gray','Light Red','Greenish Gray','Light Yellow','Light Green','Light Blue',
'Light Brown','Blue Gray','Greenish Yellow','Greenish Gray'
);
我最初的印象是,3+秒太长,用户界面无法开始填充数据。我已经将对UI的响应分解为块,这部分是高效和异步的。我从来没有想到过,简单地将SQL请求分解成具有限制和偏移量的较小块,这样服务器就可以立即使用数据响应(<200 5s),即使需要+5s才能完全完成加载。
我会就此写一个答案。
谢谢并致以良好的问候,夏莫里森
发布于 2021-09-13 04:32:25
正如推进者所指出的,
“如果您想要获得返回500万行的动态查询的良好性能,那么您将需要了解数据库引擎的复杂性,而不仅仅是SQL。不幸的是,高水平的知识无法减少它。”
我也期望如此。
我只是一次查询SQL的整个集合,这是错误的,我知道这一点。
我所做的更改将生成以下声明(我知道具体情况已经改变):
-- [145.955ms] [rows:1]
SELECT count(*)
FROM "tblWellLogs"
WHERE (
DateWellCompleted BETWEEN
'1800-01-01 06:58:00.000' AND '2021-09-12 06:00:00.000'
)
AND "FinalStatusOfWellL" NOT IN
(
5,6,7,8,9,16,27,36
)
AND WaterUseL IN
(
1,29,3,8,26,4,6
)
AND (
wyRate BETWEEN
0 AND 3321
)
AND (
TotalOrFinishedDepth BETWEEN
0 AND 248
);
Calculated total(69977) chunk (17494) currentpage(3)
-- [117.195ms] [rows:17494]
SELECT "Easting","Northing"
FROM "tblWellLogs"
WHERE (
DateWellCompleted BETWEEN
'1800-01-01 06:58:00.000' AND '2021-09-12 06:00:00.000'
)
AND "FinalStatusOfWellL" NOT IN
(
5,6,7,8,9,16,27,36
)
AND WaterUseL IN
(
1,29,3,8,26,4,6
)
AND (
wyRate BETWEEN
0 AND 3321
)
AND (
TotalOrFinishedDepth BETWEEN
0 AND 248
)
ORDER BY (SELECT NULL)
OFFSET 34988 ROWS
FETCH NEXT 17494 ROWS ONLY;
Chunk count: 17494
JSON size: 385135
Request time: 278.6612ms
对UI的响应是这样的:
GET /data/wells/xxxx/?page=3&completed.start=1800-01-01T06:58:36.000Z&completed.end=2021-09-12T06:00:00.000Z&status=supply,research,geothermal,other,unknown&use=domestic,commercial,industrial,municipal,irrigation,agriculture&depth.start=0&depth.end=248&rate.start=0&rate.end=3321&page=3 HTTP/1.1 200 385135
{
"data":[[0.0, 0.0],......],
"count": 87473,
"total": 874731,
"pages": 11,
"page": 1
}
在这种情况下,DB本质上是不可变的(我可能每年得到一次更新的数据集)。我想我可以根据查询结果大小为每个DB预定义一组块大小变化,而不仅仅是DB大小。我还将在客户端请求之前检索下一页。我在浏览器和客户端层缓存请求。只有当客户端不提供Count(*)
请求并且它不在缓存中时,我才执行它。
我确实发现,并发运行请求只会使我的CPU负担过重,所有请求几乎同时返回,但每个请求只需要+5s而不是1秒。
发布于 2021-09-03 19:35:52
几件事。
where someColumn in (null, ...)
这将不会返回someColumn
值为null
的行,因为x in (a, b, c ...)
转换为x = a or x = b or x = c
,而null
不等于null
。
你需要像这样的构造
where someColumn is null or someColumn in (...)
第二,您提到您将返回到UI的50k到500万行之间。我怀疑这是否明智..。用户界面如何呈现500万组坐标以供用户查看/使用?我想可能会有一些极端的情况,这是你真正需要做的,但这似乎是不太可能的。
第三,如果您关心的是UI响应性,那么正确的处理方法是发出异步请求。我对戈朗一无所知,但我在谷歌上快速搜索到了此页。研究这种技术。
最后,如果确实需要处理这么大的数据集,关键是确定常见的搜索条件,并与DBA讨论适当的索引。如果没有更多的模式信息,我们就无法在这方面提供太多帮助,但是如果您有一个特定的查询,需要很长时间才能使用特定的一组参数,那么您可以回来为该查询创建一个问题,并提供查询计划,我们可以帮助您解决这个问题。
https://stackoverflow.com/questions/69049703
复制相似问题