优化查询大量的" ..或COL COLNN LIKE' STRING%'或者......"

时间:2016-04-27 13:05:16

标签: sql oracle11g

当我处于绝望的深层状态时,我通常会联系StackOverflow ...所以......对于优化的任何想法或见解都将非常感激......

问题:我有一些问题,在where子句中,我有类似的东西:

    WHERE VERSION = 462
        AND (CSB_CART_MAN LIKE '12010%'
        OR CSB_CART_MAN LIKE '12011%'
        OR CSB_CART_MAN LIKE '12013%'
    .
    .
    . )
and around a thousound conditions like the ones above.
  • CSB_CART_MAN是VARCHAR2。
  • 数据大小 - 包含51列的160行。

正如所料,这是超级慢......

有关如何优化此类情况的任何想法? (一千个"或类似' XXX%'")

数据示例:

CSB_CART_MAN - 270090
CSB_CART_MAN - 2700910
CSB_CART_MAN - 13911
CSB_CART_MAN - 13912
CSB_CART_MAN - 139130

这些数字是多少? - 这些数字代表IAS,也称为"国际会计估计"

4 个答案:

答案 0 :(得分:1)

也许它适用于使用regexp_like而不是标准的? 您上面的示例可以写成:

... WHERE regexp_like(CSB_CART_MAN, '^1201[0,1,3]') 

顺便说一下:我最喜欢的地方形成一个正则表达式并测试它是https://regex101.com/

...以及新提供的数据样本:

 WITH d AS (
   SELECT 270090 CSB_CART_MAN FROM dual UNION ALL
   SELECT 2700910 CSB_CART_MAN FROM dual UNION ALL
   SELECT 13911 CSB_CART_MAN FROM dual UNION ALL
   SELECT 13912 CSB_CART_MAN FROM dual UNION ALL
   SELECT 139130 CSB_CART_MAN FROM dual 
   )
SELECT * 
  FROM d
 WHERE regexp_like(d.csb_cart_man, '^(2700|1391)\d{1,3}$')

这意味着,值必须以“2700”或“1391”开头(^),然后是1到3位数,然后到达结尾($)

答案 1 :(得分:0)

我会考虑将搜索字符串放入表格(可能是临时表格)并JOIN将其放入:

SELECT
    ...
FROM
    My_Table MT
INNER JOIN Search_Criteria SC ON MT.CSB_CART_MAN LIKE SC.string_pattern
WHERE
    version = 462

答案 2 :(得分:0)

您需要性能明智的查询,然后您必须先过滤4位数据并将此表连接到主表并再次过滤您想要的任何内容

像这样

SELECT
    MT.*
FROM
    My_Table MT
INNER JOIN(
         select * from my_table 
         where  version = 462
         cSB_CART_MAN LIKE '1201%')a
 ON a.id=mt.id
WHERE
(a.CSB_CART_MAN LIKE '12010%'
        OR a.CSB_CART_MAN LIKE '12011%'
        OR a.CSB_CART_MAN LIKE '12013%'
    .
    .
    . )

答案 3 :(得分:0)

有大约一千OR个条件,DBMS使用索引没有多大意义。必须逐个记录该表并与列表进行比较。所以我必须快速完成比较。

您使用的是LIKE模式匹配运算符。你给它一个模式,例如必须为wildchars('%'和'_')解析'12010%'。有可能找到像'1_2%345%'那样复杂的东西,所以它必须有一个相当复杂的算法来做到这一点。因此,在没有野人的情况下进行明确的比较可能要好得多:

substr(csb_cart_man, 1, 5)  = '12010'

我被告知在列上使用substr等函数会使优化器无法使用索引,而它可能会使用like 'xxx%'. That sounds kind of strange to me. If the optimizer is able to examine 'xxx%' on whether it starts with non-wildcard characters, why can't it see the 1 in substr上的索引(col,1,n )`?但无论如何,如上所述,无论如何在你的查询中使用索引是没有意义的,所以没问题。

我会写这样的查询:

select * 
from mytable 
where version = 462
and substr(csb_cart_man, 1, 5) in ('12010', '12011', '12013', ...);

因此分别为多个长度:

select * 
from mytable 
where version = 462
and 
(
  substr(csb_cart_man, 1, 5) in ('12010', '12011', '12013', ...)
  or
  substr(csb_cart_man, 1, 6) in ('120444', '120555', '120777', ...)
);

使用一个固定长度你可以尝试使用函数索引,但如上所述,我不认为它会被使用:

create index idx_fivechars on mytable( version , substr(csb_cart_man, 1, 5) );