当oracle sql查询在in(…)语句中有大量选择时,不使用索引

wrrgggsh  于 2021-08-01  发布在  Java
关注(0)|答案(1)|浏览(1378)

我有一个select语句,在in(…)语句中有很多选择。in statment的列具有非唯一索引,并且是varchar(50)。当in语句中的元素数超过某个阈值时,将不使用索引。
我的选择结构如下

SELECT T.*, RANK() OVER
 (PARTITION BY KEY_ID ORDER BY OBS_DATE ASC) AS XRANK 
FROM "MY_TABLE" T WHERE KEY_ID IN('A','B','C')

但实际上in语句中还有几百个元素,它们不被称为a、b、c。
如果我将in语句中的项数减少到50,则使用索引,查询将花费0.003s。返回7k行
如果将in station的项加倍为100,则不使用索引,并执行一次完整的表扫描,用0.4s返回14k行。
我不知道为什么不使用索引,但我想看看如果使用索引会发生什么,所以我试着给自己一个提示,

SELECT /*+ index(MY_TABLE,MY_INDEX) */ O.*, RANK() OVER ...blah blah

但是这个提示被忽略了。当我运行explain计划时,它不会被使用,并且查询的速度是相同的。
任何建议都将不胜感激,尤其是
在语句中有较多的元素时,为什么不使用索引
为什么提示被忽略了。
谢谢。

11dmarpk

11dmarpk1#

这是因为选择性。如果查询的选择性不够,那么全表扫描通常比多个索引范围扫描(不是唯一的)好。
如果值的数目较低,基于成本的优化器将考虑多个索引范围扫描的成本仍然低于全表扫描的成本。如果添加的值太多,则索引范围扫描将超过整个表扫描的成本。
现在,成本是相对的,它取决于优化器的配置方式(提示),但也取决于直方图和表统计信息。它们是最新的吗?
顺便说一下,您说选择了7k和14k行。这代表了表格的百分之几?如果它太高,引擎将忽略索引而去堆。
说了这么多,我认为这是一个非常糟糕的设计。您可以从另一个表/选择中生成这些值,而不是通过导线发送100个参数吗?

相关问题