【发布时间】:2013-02-03 23:48:21
【问题描述】:
我们的应用程序在其中一个环境中突然变慢了。我所做的唯一更改是更改了 SQL。在发布之前,SQL 是这样的
Select EmployeeId
From Employee
Where Dept='CS'
and record_state='ACTIVE'
and EmployeeTypeId ='1'
发布后的SQL是
Select EmployeeId
From Employee Where Dept='CS'
and record_state='ACTIVE'
and EmployeeTypeId IN ('1','2')
这张表的索引是employee_state_id_index (Dept,record_state,EmployeeTypeId) 索引没有改变。这个索引对新SQL没有帮助吗?新的 SQL 会扫描整个表吗?我不知道索引如何与 in 子句一起使用。感谢您的帮助和 cmets
查询的解释计划是
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | DELETE STATEMENT | | 1 | 57 | 4 (0)|
| 1 | DELETE | Employee | | | |
|* 2 | INDEX RANGE SCAN| employee_state_id_index | 1 | 57 | 4 (0)|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
2 - access("C"."Dept"='CS' AND
"C"."RECORD_STATE"='ACTIVE')
filter("C"."EmployeeTypeId"='1' OR
"C"."EmployeeTypeId"='2')
【问题讨论】:
-
检查执行计划。它会准确地告诉您是否使用了索引。您还应该告诉我们您正在使用哪个 DBMS。甲骨文? Postgres?
-
执行计划是针对
DELETE语句,但您的问题显示SELECT语句。所以显然有些事情你没有告诉我们 -
您在第一个实例中作为
number传入EmployeeTypeId,在第二个实例中传入一个字符。这可以改变计划(计划显示EmployeeTypeId是varchar2,因为Oracle 将引号保留在那里)。其次,您确定索引与您描述的完全一样吗?因为计划在EmployeeTypeId上显示过滤器而不是访问。如果在EmployeeTypeId列之前的索引中有另一列(即索引不理想),我通常会期望这一点。计划中的rows还显示为该查询估计的 1 行。如果这在很大程度上偏离了,那么这也会阻碍事情。 -
EmployeeTypeID = 2 的记录相对于 = 1 的记录有多少?如果许多行的值为 2,则优化器可能不会使用索引和表扫描。仅针对 EmployeeTypeID = 2 尝试您的原始 SQL。如果这需要很长时间,那么性能问题是您的数据而不是您的查询的函数。
-
请贴出这两个版本的执行计划。
标签: sql oracle indexing oracle10g in-clause