问一条sql执行效率的问题
獨自等待
2010-08-15
left join 应该可以 我支持 楼上的 ,但 还可以 考虑 用存储过程 100W commit一次
|
|
yunmanfan
2010-08-16
我来做的话,就写个程序,在程序里处理,是不是可行?
|
|
zhang19841017
2010-08-16
先用union all 把数据插进表C,把表A删掉, 把C表重命名为A 就可以了
select * from A union all select id, 0 as status from B into C 这样应该比left join 效率要高 |
|
grantsw
2010-08-17
查看 execute plan .
|
|
fsj0101
2010-08-20
zhang19841017 写道 先用union all 把数据插进表C,把表A删掉, 把C表重命名为A 就可以了
select * from A union all select id, 0 as status from B into C 这样应该比left join 效率要高 这样,A和B相同的数据不就重复了?还得删除重复的数据。 |
|
fsj0101
2010-08-20
改成not exists 应该不会太慢,1000万的数据,保守1个小时之内
|
|
今夜有雨
2010-08-20
谢谢大家,最后采用了full join的方式,两张表full join一下,存入第三张表。
|
|
dingjun1
2010-08-20
测试过程 原来的表cons,customerid客户ID,这是存放的打卡记录,共有6403364行,不同customerid数:30568,在customerid创建了索引。 create table test_my as select customerid,opcount from cons;/*15 seconds*/ create index test_my_cid on test_my(customerid);/*40 seconds*/ 去掉两个customerid delete from test_my where customerid in(28158,16); commit; 执行下面的三条语句 从一个表中查询另一个表不存在的customerid。 select/*+ gather_plan_statistics */ customerid,opcount from test_my t where not exists(select customerid from cons a where t.customerid=a.customerid); select/*+ gather_plan_statistics */ * from ( select customerid from cons minus select customerid from test_my ); select/*+ gather_plan_statistics */ a.customerid from cons a left join test_my b on (a.customerid=b.customerid ) where b.customerid is null; --这条SQL把表写反了,但是不影响参考 select/*+ gather_plan_statistics */ customerid,opcount from test_my t where not exists(select customerid from cons a where t.customerid=a.customerid); call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 1 6.90 19.96 37714 26275 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 3 6.90 19.97 37714 26275 0 0 Rows Row Source Operation ------- --------------------------------------------------- 0 HASH JOIN RIGHT ANTI (cr=26275 pr=37714 pw=19530 time=19969254 us) 6403364 INDEX FAST FULL SCAN I_CONS_CUSTOMERID (cr=14109 pr=6554 pw=0 time=10193 us)(object id 152141) 6403069 TABLE ACCESS FULL TEST_MY (cr=12166 pr=11630 pw=0 time=10970 us) select/*+ gather_plan_statistics */ * from ( select customerid from cons minus select customerid from test_my ) call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 1 12.96 21.91 59457 61308 0 2 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 3 12.96 21.91 59457 61308 0 2 Rows Row Source Operation ------- --------------------------------------------------- 2 VIEW (cr=61308 pr=59457 pw=0 time=21909468 us) 2 MINUS (cr=61308 pr=59457 pw=0 time=21909463 us) 30568 SORT UNIQUE (cr=49142 pr=47514 pw=0 time=13923686 us) 6403364 TABLE ACCESS FULL CONS (cr=49142 pr=47514 pw=0 time=6403410 us) 30566 SORT UNIQUE (cr=12166 pr=11943 pw=0 time=7971044 us) 6403069 TABLE ACCESS FULL TEST_MY (cr=12166 pr=11943 pw=0 time=12481 us) 没有做distinct 一个customerid存在多条记录 select/*+ gather_plan_statistics */ a.customerid from cons a left join test_my b on (a.customerid=b.customerid ) where b.customerid is null call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 3 6.85 21.35 65211 61308 0 295 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 5 6.85 21.35 65211 61308 0 295 Misses in library cache during parse: 1 Optimizer mode: ALL_ROWS Parsing user id: 57 Rows Row Source Operation ------- --------------------------------------------------- 295 HASH JOIN RIGHT ANTI (cr=61308 pr=65211 pw=16647 time=16633288 us) 6403069 TABLE ACCESS FULL TEST_MY (cr=12166 pr=0 pw=0 time=49 us) 6403364 TABLE ACCESS FULL CONS (cr=49142 pr=48564 pw=0 time=19226485 us) ------------------------------------------------------------------------------------------- 从执行计划上看,not exists会被优化器 优化为半连接。 如果走索引INDEX FAST FULL SCAN会减少一些逻辑读。 select/*+ gather_plan_statistics */ customerid,opcount from test_my where customerid not in(select customerid from cons) 这条SQL实在太慢了,就没有等。 执行过程应该是从test_my中取出一条记录,然后就到cons中进行扫描一次,那么逻辑读大致可以理解为test_my * cons; 其它的三种方式逻辑读大致可以理解为test_my + cons。不同的是创建hash表过滤 与 唯一值排序后过滤的区别。 |
|
dingjun1
2010-08-20
今夜有雨 写道 谢谢大家,最后采用了full join的方式,两张表full join一下,存入第三张表。
40秒内能完成么? |
|
TeddyWang
2010-08-24
我爱小白 写道 可以采用临时表,通过临时表把数据插入A中去
我觉得这个比较可行,在orale10g以后你可以使用forall来执行整块的插入。 首先把符合要求的数据弄出来放在全局临时表中,然后用forall来1000件1000件的载入,问题应该不大。 效率大概在每40000件5分钟左右。 TYPE data_ttype IS TABLE OF A%ROWTYPE INDEX BY PLS_INTEGER; data_tbl data_ttype; FORALL i IN INDICES OF data_tbl SAVE EXCEPTIONS INSERT INTO A VALUES data_tbl(i); 但是如果你的目标表是在dblink从另一个数据库影射过来的话,forall不好用。 |