【问题标题】:how to improve the performance on this type of Query?如何提高此类查询的性能?
【发布时间】:2013-12-30 18:21:36
【问题描述】:

我有一个查询,我正在搜索一系列用户帐户,但每次我通过查询时,我都会使用多个 ID 号的前 5 位数字,并以此为基础进行搜索。我想知道当我们使用超过 10 个用户 ID 进行搜索时,是否有其他方法可以为用户 ID 范围重写此查询?这种查询中的搜索是否会对性能造成巨大影响?

示例:

select A.col1,B.col2,B.col3
from table1 A,table2 B
where A.col2=B.col2
and (B.col_id like '12345%' 
OR B.col_id like '47474%' 
OR B.col_id like '59598%');

我正在使用 Oracle11g。

【问题讨论】:

  • "如何避免在sql查询中使用OR?"这是一个错误的问题。正确的问题:“我怎样才能提高这个查询的性能?”。不要在查询中随意选择一些东西并决定让它消失。
  • 在查询中使用OR 不一定有什么问题。但是我建议不要使用 pre ANSI 92 join 语法。而不是from table1 A, Table2 B 使用FROM table1 A INNER JOIN Table2 B ON A.Col2 = B.col2
  • 用你的搜索值创建一个临时表并正确加入它,它会清理丑陋的
  • 您的查询中的C.col_id 是什么?你又错过了一张桌子吗?
  • 抱歉,一直是 b.col_id。

标签: sql performance oracle11g


【解决方案1】:

实际上,将多少个 UserID 传递给查询并不重要。最重要的部分是查询的选择性。换句话说:有多少行将返回您的查询以及表中有多少行。如果返回的行数相对较少,那么最好在列B.col_id 上创建索引。使用OR 条件也没有什么不好。基本上每个OR 都会在执行计划中再添加一个INDEX RANGE SCAN,最终CONCATENATION (但您宁愿检查您的实际计划以确定)。如果所有这些操作的总成本低于全表扫描,那么 Oracle CBO 将使用您的索引。在其他情况下,如果您一次选择 >=20-30% 的数据,则最有可能发生全表扫描,您更不用担心OR,因为将读取所有数据并将每个值与您的多个条件进行比较不会增加太多开销。

【讨论】:

    【解决方案2】:

    通常使用 LIKE 会使 Oracle 无法使用索引。

    如果要重复使用查询,请考虑使用 COL_ID 的前 5 个字符创建一个合成列。在其上放置一个非唯一索引。将您的搜索键放在一个表中并将其连接到该列。

    可能有一种方法可以在前 5 个字符上使用功能索引。

    【讨论】:

    • 更准确的说法是“通常使用 LIKE 在左侧 使得 Oracle 无法使用索引。” col_id 上的简单索引在这里可能就足够了。对我来说,这似乎是过早的优化。
    • 有趣。为什么这么说?
    • @EvilTeach 自己试试。运行看看select的执行计划。 create table t_test as select * from all_objects; create index tt_indx on t_test(object_name); select * from t_test t where t.object_name like 'I_OBJ%';你会发现有点漂亮INDEX RANGE SCAN。将通配符放在开头'%I_OBJ',它将是TABLE ACCESS FULL。所以@jonearles 是对的,上面的陈述中只漏了一个词。 Generally the use of LIKE *with wildcard* on the left side makes it impossible for Oracle to use indexes.
    【解决方案3】:

    我不知道性能会不会更好,但是另一种写法是使用联合:

    select A.col1,B.col2,B.col3
      from table1 A,table2 B
      where A.col2=B.col2
      and (A.col_id like '12345%')
    union all
    select A.col1,B.col2,B.col3
      from table1 A,table2 B
      where A.col2=B.col2
      and (A.col_id like '47474%')  -- you did mean A.col_id again, right?
    union all
    select A.col1,B.col2,B.col3
      from table1 A,table2 B
      where A.col2=B.col2
      and (A.col_id like '59598%');  -- and A.col_id here too?
    

    【讨论】:

    • 为了匹配问题的逻辑,您需要使用 union all。
    • 我们不能使用联合,因为我们可能需要不时地传递更多的值,比如更多 10。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 2019-03-20
    • 1970-01-01
    相关资源
    最近更新 更多