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

时间:2018-09-19 09:58:41

标签: sql oracle query-performance

我写了一个查询来获取NULL DAYS记录(偶尔,休假,紧急假期),后来我在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表数据格式

enter image description here

1 个答案:

答案 0 :(得分:2)

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

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

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

通用方法如下:

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

在不了解更多详细信息的情况下,我无法提出更多建议。希望对您有所帮助。

根据上传的数据进行编辑

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