我正在进行SQL查询,并尝试对其进行优化,因为执行时间太长。
我之间有一些选择和UNION。 每个select都在同一个表上,但在WHERE子句中具有不同的条件。 基本上我总是喜欢这样的东西:
select * from A
where field1 <=TO_DATE ('01/01/2010', 'DD/MM/YYYY')
AND field1 >= TO_DATE(some date)
and field2 IN (...)
UNION
select * from A
where field1 <=TO_DATE ('01/01/2010', 'DD/MM/YYYY')
AND field1 >= TO_DATE(some date2)
and field2 =(...)
UNION
....
我在field1上有一个索引(它是一个日期字段,而field2是一个数字)。 现在,当我选择时,如果我只选择
WHERE field1 <TO_DATE ('01/01/2010', 'DD/MM/YYYY')
它不使用索引。 我正在使用Toad看到解释清楚,它说:
SELECT STAITEMENT Optimiser Mode = CHOOSE
TABLE ACCESS FULL
这是一个庞大的表,此列的索引就在那里。
关于这个优化器的任何想法?为什么它不使用索引?
另一个问题是,如果我在field1和field2上有where子句,我必须为每个字段只创建一个索引或一个索引吗?
答案 0 :(得分:1)
如果没有联盟并且在你的不同条款之间使用OR,你会不会感觉更好?
select * from A
where (
field1 <"toto"
and field2 IN (...)
)
OR
(
field1 >"toto2"
and field2 IN (...)
)
OR
....
也可以在2列上建立索引。
CREATE INDEX index_name
ON A (field1, field2);
答案 1 :(得分:0)
您可以在两列上创建一个索引。但是您的问题将field1
视为上面的字符串,然后像下面的日期一样。这是故意的吗?此外,优化器根据其思考选择。那么你的统计数据是最新的吗?如果没有,它可能会认为FTS是找到所需记录的最佳方式。
答案 2 :(得分:0)
关于这个优化器的任何想法?为什么它不使用索引?
最可能是因为这种情况
field1 < '12/12/2010'
返回所有或几乎所有行。
在这种情况下,FULL TABLE SCAN
更好。
另一个问题是,如果我在field1和field2上有where子句,我必须为每个字段只创建一个索引或一个索引吗?
对于此查询:
select * from A
where field1 <"toto"
and field2 IN (...)
,您需要创建一个复合索引:
CREATE INDEX ix_a_2_1 ON A (field2, field1)
这将使用INLIST ITERATOR
将查询拆分为多个连续范围,并使用INDEX RANGE SCAN
返回每个范围的值。
答案 3 :(得分:0)
由于您正在处理field1的日期,因此您想使用TO_DATE。例如,WHERE field1 < TO_DATE('2010/12/12 12:00:00', 'yyyy/mm/dd hh24:mi:ss')
。
该字段的索引类型是什么?我假设一个b树索引,在这种情况下,less-than运算符是正常的,但优化器可能决定不使用它,具体取决于当前表统计信息。如果要强制使用索引,可以在提示中指定它,看看它如何影响性能。
SELECT /*+ index(tbl.INDEX_NAME) */
tbl.*
FROM A tbl WHERE field1 < TO_DATE('2010/12/12 12:00:00','yyyy/mm/dd hh24:mi:ss');
至于最后一个问题,您可以单独为每列创建索引,也可以使用两列创建复合索引。如果您总是要根据两列中的值进行选择,那么这两列上的复合索引可能会更好。
答案 4 :(得分:-1)
我不是最大的Oracle专家,但我想你在使用'&gt;'时无法获得索引的优势或'&lt;'运营商。索引提供了一种快速查找特定值的方法,而不是一系列值。因此,当您查找“小于”特定值的值时,索引不执行任何操作。