减少查询响应时间,需要优化查询

Posted

技术标签:

【中文标题】减少查询响应时间,需要优化查询【英文标题】:Reduce the query response time, need to optimise the query 【发布时间】:2018-09-19 09:58:41 【问题描述】:

我写了一个查询来获取 NULL DAYS (Occasion,weekoff,emergency holiday) 的记录,后来我在 GUI 中实现了同样的功能,所以我的管理员可以看到列表,加载数据需要几分钟,甚至在我的 SQL 开发人员中。

如何减少执行时间?

这里是查询

SELECT *
FROM
  (SELECT s.null_id ,
    STRING_AGG(DISTINCT s.city) city_id ,
    STRING_AGG(DISTINCT c.name) cityName ,
    STRING_AGG(DISTINCT s.location) location_id ,
    STRING_AGG(DISTINCT l.name) locationName ,
    STRING_AGG(DISTINCT s.sublocation) sublocation_id ,
    STRING_AGG(DISTINCT sl.name) sublocationName ,
    s.department ,
    s.fromtodate ,
    s.todate ,
    s.remark ,
    s.status ,
    s.update_date ,
    s.update_by ,
    s.delete_status ,
    s.update_by_name ,
    uu.name updatedBy ,
    row_number() OVER(ORDER BY s.null_id) rnum
  FROM nullday s
  LEFT OUTER JOIN userdetail uu
  ON s.update_by = uu.user_id
  LEFT OUTER JOIN city c
  ON ','
    || s.city
    || ',' LIKE '%,'
    ||c.CITY_ID
    ||',%'
  LEFT OUTER JOIN location l
  ON ','
    || s.location
    || ',' LIKE '%,'
    ||l.LOCATION_ID
    ||',%'
  LEFT OUTER JOIN sublocation sl
  ON ','
    || s.sublocation
    || ',' LIKE '%,'
    ||sl.SUBLOCATION_ID
    ||',%'
  WHERE s.null_id = s.null_id
  GROUP BY s.null_id,
    s.location,
    s.sublocation,
    s.department,
    s.fromtodate,
    s.todate,
    s.remark ,
    s.status,
    s.update_date,
    s.update_by,
    s.delete_status,
    s.update_by_name,
    uu.name
  ORDER BY s.fromtodate ASC
  ) mytbl
WHERE rnum < :max_val
AND rnum   > :min_val

我无法弄清楚,joinsLISTAGG 是否需要时间来加载查询。

NULLDAY 表数据格式

【问题讨论】:

第一个问题是您的数据充满了 CSV 列表,然后您根据 CSV 列表中是否存在值来连接其他表。正确规范您的数据库.. 与当前查询相关的任何其他建议,因为我们的数据库非常庞大,我们无法对其进行规范化,这将对我们的项目产生严重影响 显示一些数据,但我全部选择“不;通过将逗号分隔的城市 ID 列表放在nullday 记录。如果 nullday 和 city 之间的关系是多:多,那么应该有一个中间人表 nullday_city 将关系分解为两个多:一关系。整理你的数据,否则它会一次又一次地回来咬你。您可以附加地执行此操作(制作中间人表,从 CSV 列填充它,同时维护两者,逐步淘汰 CSV) ps; “这是一个糟糕的设计决定”的批评并不止于 nullday:city - 看起来你到处都这样做了。太可怕了 :o 如果你决心坚持下去,帮你的数据库一个忙,让前端解压这些数据;不要让数据库去做 附加了一个 png 文件,我在其中捕获了 NULLDAY 表数据 【参考方案1】:

这里的一个重要问题是您在表达式上连接表,而不是在实际列上。这排除了使用可能加速该过程的索引。

LEFT OUTER JOIN city c
  ON ','
    || s.city
    || ',' LIKE '%,'
    ||c.CITY_ID
    ||',%'

一种可能的解决方案是创建一个临时(或辅助)表,您可以在其中使用逗号分隔的列表和原始主键创建单独的行。您可以使用它来更快地检索主键。

通用方法可能如下:

我们能否将长查询分解成更小的块? 我们可以使用临时表代替连接表达式吗? 我们能否设计临时表以将 LEFT JOIN 替换为 INNER JOIN? 我们可以减少 DISTINCT 的数量吗? 我们可以删除 ORDER BY 吗? 我们能否删除(或使用临时表重做)row_number() OVER(ORDER BY s.null_id)? 我们能否重新设计数据库以将数据保存在关系数据库中? (正确的列和记录可以在索引中使用,逗号分隔的字符串不能。)

在不了解更多细节的情况下,我无法提出更多建议。希望对你有帮助。

根据上传的数据进行编辑

您应该提取逗号分隔的列表并创建正确的一对多关系。如果允许您更改数据库结构,请使用永久表,否则在您修改查询时使用临时表。

【讨论】:

okkk同意了,你能在同一个查询中实现上述点吗 首先通过分解逗号分隔的列表来创建 locationsublocation 表。这将大大减少查询时间。 我的意思是创建nullday_citynullday_locationnullday_sublocation,其中每条记录都有主键(s ) 的 nullday 表,以及单个 citylocationsublocation 编号。在您的查询中,您可以将此表连接到 nullday 以及 citylocationsublocation 表。例如,nullday_city 将被放置在 nulldaycity 之间。 在当前查询中,系统必须对nullday表中的每条记录进行拼接。通过使用新表,您可以在本机列上创建连接,而不是表达式。这些列可以被索引,这进一步提高了速度。 好的 Miklos 非常感谢你,我认为重复连接会导致性能低下问题。最后一个请求,你能用一些例子来演示一下,所以我会和我的技术总监讨论这个问题,所以我们的数据库开发人员将能够实现相同的

以上是关于减少查询响应时间,需要优化查询的主要内容,如果未能解决你的问题,请参考以下文章

php 实现页面静态化 1-2关于优化页面响应时间

如何在Python中将API响应时间减少89.30%

MySQL--查询性能优化

如何优化这个大表SQL查询的响应时间?

响应式网站01

查询性能优化