如何修复我的查询,使过滤器不会减慢它的速度



这个问题很直接,但我想的答案不是。。

我有一个查询运行得很快,不到一秒钟。但是,如果我将许多值传递给筛选条件,它会大大降低速度。

例如,它的运行速度如下:

SELECT * FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)

但是,如果我添加以下内容,同样的代码运行速度会非常慢:

SELECT * FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
AND MYVALUE IN ('A', 'B', 'C', 'D', 'E')

有什么可以用SQL来修改的吗。我的目标是让查询快速运行,最好是在一秒钟之内。

我试过GROUP BY,但没有什么不同。

我已经排除了所有的可能性,问题出在IN (multiple values)部分。

有什么想法吗?

这对于注释来说太长了。

你是如何衡量第一个查询的速度的?一种可能性是,您正在测量返回的第一个值的速度,而不是最后一个值——Oracle发现返回满足第一个条件的值很容易。检查这一点的一种方法是使用order by,因为这需要获取所有行(然后做更多的工作):

SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
ORDER BY othercol;

ORDER BY通常会处理所有数据。)

假设你没有犯那个错误,另一个潜在的问题就是索引的使用。Oracle通常对此非常擅长。并且,您可以使用执行计划来查看执行计划是否相同。例如,您可能在date_columnmyvalue上分别有一个索引。Oracle可能选择了错误的索引。

如果是这种情况,您可以在(myvalue, datecol)上创建一个索引,并尝试运行以下查询:

SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30) AND
      MYVALUE = 'A';

如果运行速度很快,请尝试对查询进行索引。如果不起作用,请使用UNION ALL:

SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30) AND MYVALUE = 'A'
UNION ALL
SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30) AND MYVALUE = 'B'
UNION ALL
. . .

1)找出用于第一个查询的实际索引(您可以查看"解释计划"),然后向第二个SQL添加提示/**+索引(MYTABLE MYINDEX)*/,以确保也使用相同的索引

2) 使用下面的SQL强制首先处理子查询

SELECT * FROM (
  SELECT /*+no_merge*/ ROWNUM row_num, t.* FROM MYTABLE t
  WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
) WHERE MYVALUE IN ('A', 'B', 'C', 'D', 'E')

我觉得可以通过使用解释计划来检查查询是否运行得更快,看看内部发生了什么。我建议:

  • 检查两个查询的解释计划,看看执行方式有什么不同
  • myvalue列上可能没有索引,这会影响查询的性能
  • 无论如何,在看到两个查询的实际解释计划后,可以说更多

希望这有助于缩小问题的范围。

最新更新