Oracle 如何加快查询中的substr搜索

Oracle 如何加快查询中的substr搜索,oracle,substr,substring,Oracle,Substr,Substring,我使用它作为子选择(在一个连接其他两个表的简单查询中),正如您所想象的,它需要一段时间才能运行。到目前为止已经持续了6个多小时。 这是唯一的办法吗?我知道做另一个连接而不是子选择可能会有所帮助。但主要的瓶颈是所有这些OR和子字符串 SELECT ex_array FROM service_x WHERE ( substr(ex_array,1,2) = 'FW' OR substr(ex_array,3,2) = 'FW' OR substr(ex_array,5,2) = 'F

我使用它作为子选择(在一个连接其他两个表的简单查询中),正如您所想象的,它需要一段时间才能运行。到目前为止已经持续了6个多小时。 这是唯一的办法吗?我知道做另一个连接而不是子选择可能会有所帮助。但主要的瓶颈是所有这些OR和子字符串

SELECT ex_array
FROM   service_x 
WHERE  
   ( substr(ex_array,1,2) = 'FW' OR substr(ex_array,3,2) = 'FW' OR substr(ex_array,5,2) = 'FW' OR substr(ex_array,7,2) = 'FW' OR substr(ex_array,9,2) = 'FW' OR substr(ex_array,11,2) = 'FW' ) 
OR ( substr(ex_array,1,2) = 'IL' OR substr(ex_array,3,2) = 'IL' OR substr(ex_array,5,2) = 'IL' OR substr(ex_array,7,2) = 'IL' OR substr(ex_array,9,2) = 'IL' OR substr(ex_array,11,2) = 'IL' )  
OR ( substr(ex_array,1,2) = 'IN' OR substr(ex_array,3,2) = 'IN' OR substr(ex_array,5,2) = 'IN' OR substr(ex_array,7,2) = 'IN' OR substr(ex_array,9,2) = 'IN' OR substr(ex_array,11,2) = 'IN' )  
OR ( substr(ex_array,1,2) = 'IK' OR substr(ex_array,3,2) = 'IK' OR substr(ex_array,5,2) = 'IK' OR substr(ex_array,7,2) = 'IK' OR substr(ex_array,9,2) = 'IK' OR substr(ex_array,11,2) = 'IK' )  
OR ( substr(ex_array,1,2) = 'IH' OR substr(ex_array,3,2) = 'IH' OR substr(ex_array,5,2) = 'IH' OR substr(ex_array,7,2) = 'IH' OR substr(ex_array,9,2) = 'IH' OR substr(ex_array,11,2) = 'IH' )  
OR ( substr(ex_array,1,2) = 'KP' OR substr(ex_array,3,2) = 'KP' OR substr(ex_array,5,2) = 'KP' OR substr(ex_array,7,2) = 'KP' OR substr(ex_array,9,2) = 'KP' OR substr(ex_array,11,2) = 'KP' )  
)

你可以尝试的一件事是使用。具体来说,在substr(ex_数组,3,2)和substr(ex_数组,9,2)等基础上创建基于函数的索引

不过,它可能有很多索引,因此您必须权衡运行一些测试对您有多大帮助。但这是一个开始的想法


我假设您使用的是8i或更高版本。

您可以尝试的一件事是使用一个。具体来说,在substr(ex_数组,3,2)和substr(ex_数组,9,2)等基础上创建基于函数的索引

不过,它可能有很多索引,因此您必须权衡运行一些测试对您有多大帮助。但这是一个开始的想法


我假设您使用的是8i或更高版本。

这种结构如何

INSTR( ex_array, 'FW' ) IN (1,3,5,7,9,11)

那么至少你只需要做一次字符串解析…

这个结构怎么样

INSTR( ex_array, 'FW' ) IN (1,3,5,7,9,11)
那么至少您只需要执行一次字符串解析…

可能需要:

(正则表达式可能编写得更好…)

您还可以根据建议添加基于函数的索引(尽管您只需要一个):

以及将查询更改为使用:

REGEXP_INSTR(ex_array, '^(.{2}){0,5}(FW|IL|IN|IK|IH|KP).*$') = 1
可能是:

(正则表达式可能编写得更好…)

您还可以根据建议添加基于函数的索引(尽管您只需要一个):

以及将查询更改为使用:

REGEXP_INSTR(ex_array, '^(.{2}){0,5}(FW|IL|IN|IK|IH|KP).*$') = 1

鉴于我建议提供的信息,鉴于您需要的查询的选择性:

1) ex_数组上的索引(最好只是ex_数组,或者在索引的前缘上带有ex_数组)

2) 以修改查询。如果附加其他筛选条件:

。。。 及(Ex_数组(如“%FW%”或Ex_数组(如“%IL%”)或Ex_aray like…)涵盖了这六种情况中的每种情况。索引到位后,这将启用索引范围扫描,以将1220万行减少到仅包含您感兴趣的六个字符串之一的行。然后,只有这些行将应用substr逻辑,而不使用17.5万美元

原则上,这会提高效率。但这在很大程度上取决于数据分布(例如,可能所有1200万行都包含六个字符串中的一个,只是不在原始查询中指定的位置。在这种情况下,我建议的更改可能比原始查询的效率低).可能还有其他选择,但我需要更多信息,包括更准确地解释计划


希望这有帮助-祝你好运!!

鉴于我建议的可用信息,鉴于你需要的查询的选择性:

1) ex_数组上的索引(最好只是ex_数组,或者在索引的前缘上带有ex_数组)

2) 修改查询。如果附加其他筛选条件:

。。。 及(Ex_数组(如“%FW%”或Ex_数组(如“%IL%”)或Ex_aray like…)涵盖了这六种情况中的每种情况。索引到位后,这将启用索引范围扫描,以将1220万行减少到仅包含您感兴趣的六个字符串之一的行。然后,只有这些行将应用substr逻辑,而不使用17.5万美元

原则上,这会提高效率。但这在很大程度上取决于数据分布(例如,可能所有1200万行都包含六个字符串中的一个,只是不在原始查询中指定的位置。在这种情况下,我建议的更改可能比原始查询的效率低).可能还有其他选择,但我需要更多信息,包括更准确地解释计划


希望这有帮助-祝你好运!!

你有查询的解释计划吗(请查看dbms\u xplan以获取此信息)?我希望通过对ex_数组应用函数来停止使用任何标准索引的数据库后,可以通过完整的表扫描来满足查询。@dcp建议的六个基于函数的索引可能会有所帮助。service_x有多少行,以及您希望查询返回的行的百分比是多少?您可以重新评估整体算法/设计以获得所需的性能。但关键可能是启用索引访问,这取决于查询选择性。大约1220万行(在服务中)我应该会得到大约175000个结果。考虑到查询的高选择性-我建议如果您无法优化整个算法,您最好的选择是修改查询,通过对ex_数组的索引访问来实现对行的高效筛选。我将在下面发布一个答案,这可能会有所帮助。您有查询的解释计划吗(请查看dbms_xplan以获取此信息)?我希望通过对ex_数组应用函数来停止使用任何标准索引的数据库后,可以通过完整的表扫描来满足查询。@dcp建议的六个基于函数的索引可能会有所帮助。service_x有多少行,以及您希望查询返回的行的百分比是多少?您可以重新评估整体算法/设计以获得所需的性能。但关键可能是启用索引访问,这取决于查询选择性。大约1220万行(在服务中)我应该会得到大约175000个结果。考虑到查询的高选择性-我建议,如果您无法优化整个算法,您最好的选择是修改查询,通过对ex_数组的索引访问来实现对行的高效筛选。我将在下面发布一个答案,这可能会有所帮助。这很好,但正如@mathewbutler所说的-t他真正的进步将是当有一个指数的时候,只要小心你是