这个问题很直接,但我想的答案不是。。
我有一个查询运行得很快,不到一秒钟。但是,如果我将许多值传递给筛选条件,它会大大降低速度。
例如,它的运行速度如下:
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_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)找出用于第一个查询的实际索引(您可以查看"解释计划"),然后向第二个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列上可能没有索引,这会影响查询的性能
- 无论如何,在看到两个查询的实际解释计划后,可以说更多
希望这有助于缩小问题的范围。