【问题标题】:Performance of query with OR condition between join tables在连接表之间使用 OR 条件进行查询的性能
【发布时间】:2012-10-31 01:27:14
【问题描述】:

有两个表,tparent 和 tchild,它们是使用脚本 #1 创建的。 需要查询uname等于'sky'的两个表中的所有信息。 当只有少量记录时,以下查询语句 #2 很快。 但是当使用以下脚本#3 插入大量记录时,它会变得非常缓慢。 我认为这是由表之间的 OR 条件引起的,索引对查询没有用处。 所以我得到了一个快速的解决方案,将语句更改为三个子语句和联合结果,如#4。 我想知道有没有更好的解决方案?那是什么?

谢谢!

#1

drop table tparent;
drop table tchild;
create table tparent(typeid int,sno number,uname varchar2(50) );
create table tchild(typeid int,sno number,seqno int,uname varchar2(50));
create unique index uidx_tparent_typeidsno on tparent(typeid,sno);
create unique index uidx_tchild_typeidsnoseqno on tchild(typeid,sno,seqno);
create index idx_tparent_name on tparent(uname);
create index idx_tchild_name on tchild(uname);

insert into tparent values (1,10,'lily');
insert into tparent values (1,11,'eric');
insert into tparent values (2,10,'tom');
insert into tparent values (2,11,'eric');
insert into tparent values (3,10,'sky');

insert into tchild values (1,10,1,'sam');
insert into tchild values (1,10,2,'sky');
insert into tchild values (1,11,1,'eric');
insert into tchild values (1,11,2,'john');
insert into tchild values (2,10,1,'sky');
insert into tchild values (2,11,1,'eric');
insert into tchild values (3,10,1,'tony');

#2

select p.typeid,p.sno,p.uname,c1.uname as uname1,c2.uname as uname2 from tparent p
  left join tchild c1 on c1.typeid=p.typeid and c1.sno = p.sno and c1.seqno=1
  left join tchild c2 on c2.typeid=p.typeid and c2.sno = p.sno and c2.seqno=2
where (p.uname='sky' or c1.uname='sky' or c2.uname='sky');

#3

BEGIN
    FOR x IN 1..10
    LOOP
        BEGIN
            FOR y IN 10000..100000
            LOOP
                BEGIN
                    insert into tparent values (x,y,'name'|| y);
                    insert into tchild values (x,y,1,'name'|| y);
                    insert into tchild values (x,y,2,'name'|| y);
                END;
            END LOOP;
            COMMIT;
        END;
    END LOOP;
END;

#4

select typeid,sno,max(uname),max(uname1),max(uname2) from (

select p.typeid,p.sno,p.uname,c1.uname as uname1,c2.uname as uname2 from tparent p
  left join tchild c1 on c1.typeid=p.typeid and c1.sno = p.sno and c1.seqno=1
  left join tchild c2 on c2.typeid=p.typeid and c2.sno = p.sno and c2.seqno=2
where (p.uname='sky' )
union 
select p.typeid,p.sno,p.uname,c1.uname as uname1,c2.uname as uname2 from tparent p
  left join tchild c1 on c1.typeid=p.typeid and c1.sno = p.sno and c1.seqno=1
  left join tchild c2 on c2.typeid=p.typeid and c2.sno = p.sno and c2.seqno=2
where ( c1.uname='sky' )
union

select p.typeid,p.sno,p.uname,c1.uname as uname1,c2.uname as uname2 from tparent p
  left join tchild c1 on c1.typeid=p.typeid and c1.sno = p.sno and c1.seqno=1
  left join tchild c2 on c2.typeid=p.typeid and c2.sno = p.sno and c2.seqno=2
where ( c2.uname='sky')
) tb group by typeid,sno
order by typeid,sno
;

【问题讨论】:

  • 即使在 p.uname 上使用索引也很慢?以及您使用的是哪种索引。您能否也给我们解释一下大型查询?
  • #3.5 exec dbms_stats.gather_table_stats(...)
  • 我认为您在 #4 中的 group by 是多余的,因为您的工会已经丢弃了重复项。如果你在做所有的联合,你会需要它。并不是说这回答了你的问题......
  • 文森特,谢谢!但执行dbms_stats.gather_table_stats后没有明显改善。
  • 我认为过滤谓词(where)如果在连接表之间包含 OR 条件,则不能在连接之前进行过滤。对吗?

标签: sql performance oracle query-optimization


【解决方案1】:

您应该在 from 子句中使用“union all”,然后按 group by。

【讨论】:

    猜你喜欢
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多