减少查询响应时间,需要优化查询
Reduce the query response time, need to optimise the query
我写了一个查询来获取 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
我无法弄清楚 joins
或 LISTAGG
是否需要时间来加载查询。
NULLDAY Table 数据格式
此处的重要问题之一是您在表达式上加入 tables,而不是在实际列上。这排除了可能会加速该过程的索引的使用。
LEFT OUTER JOIN city c
ON ','
|| s.city
|| ',' LIKE '%,'
||c.CITY_ID
||',%'
一个可能的解决方案是创建一个临时(或辅助)table,您可以在其中使用逗号分隔列表和原始主键创建单独的行。您可以使用它来更快地检索主键。
通用方法如下:
- 我们能否将长查询分解成更小的块?
- 我们可以使用临时 table 代替连接表达式吗?
- 我们可以设计临时 tables 来用 INNER JOIN 替换 LEFT JOIN 吗?
- 我们可以减少 DISTINCT 的数量吗?
- 我们可以删除 ORDER BY 吗?
- 我们能否删除(或使用临时 tables 返工)row_number() OVER(ORDER BY s.null_id)?
- 我们能否重新设计数据库以按照关系数据库中应有的方式保存数据? (正确的列和记录可以在索引中使用,逗号分隔的字符串不能。)
在不了解更多细节的情况下,我无法提供更多建议。希望对你有帮助。
根据上传的数据进行编辑
您应该提取逗号分隔的列表并创建适当的一对多关系。如果允许更改数据库结构,请使用永久 tables,否则在重新处理查询时使用临时 tables。
我写了一个查询来获取 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
我无法弄清楚 joins
或 LISTAGG
是否需要时间来加载查询。
NULLDAY Table 数据格式
此处的重要问题之一是您在表达式上加入 tables,而不是在实际列上。这排除了可能会加速该过程的索引的使用。
LEFT OUTER JOIN city c
ON ','
|| s.city
|| ',' LIKE '%,'
||c.CITY_ID
||',%'
一个可能的解决方案是创建一个临时(或辅助)table,您可以在其中使用逗号分隔列表和原始主键创建单独的行。您可以使用它来更快地检索主键。
通用方法如下:
- 我们能否将长查询分解成更小的块?
- 我们可以使用临时 table 代替连接表达式吗?
- 我们可以设计临时 tables 来用 INNER JOIN 替换 LEFT JOIN 吗?
- 我们可以减少 DISTINCT 的数量吗?
- 我们可以删除 ORDER BY 吗?
- 我们能否删除(或使用临时 tables 返工)row_number() OVER(ORDER BY s.null_id)?
- 我们能否重新设计数据库以按照关系数据库中应有的方式保存数据? (正确的列和记录可以在索引中使用,逗号分隔的字符串不能。)
在不了解更多细节的情况下,我无法提供更多建议。希望对你有帮助。
根据上传的数据进行编辑
您应该提取逗号分隔的列表并创建适当的一对多关系。如果允许更改数据库结构,请使用永久 tables,否则在重新处理查询时使用临时 tables。