这个问题很简单但我想的答案不是......
我有一个快速运行的查询 - 在一秒钟之内。但是,如果我将许多值传递给过滤条件,那么它会减慢很多。
例如,它运行速度很快:
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)
部分。
有什么想法吗?
答案 0 :(得分:1)
评论太长了。
您如何衡量第一个查询的速度?一种可能性是您正在测量返回的 first 值的速度而不是最后一个值 - 并且Oracle发现很容易返回满足第一个条件的值。检查此问题的一种方法是使用order by
,因为这需要获取所有行(然后执行更多工作):
SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
ORDER BY othercol;
(ORDER BY
通常会处理所有数据。)
假设你没有犯这个错误,另一个潜在的问题是使用索引。 Oracle通常对此非常满意。并且,您可以使用执行计划来查看执行计划是否相同。例如,您可能在date_column
上有一个索引,在myvalue
上有一个索引。 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 :(得分:0)
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')
答案 2 :(得分:0)
我觉得可以通过使用解释计划查看查询是否运行得更快,以查看内部发生的情况。 我建议:
希望这有助于缩小问题范围。