- 论坛徽章:
- 0
|
digital unix,sybase12.0。设表A和表B,分别有记录500万条和500条,均有字段X和Y,且均有索引,X还是A的主键。执行如下语句:update b set y=a.y from a where a.x=b.x,结果可能要一个多小时才能完成,有时也很快,几秒钟就搞定。
索引应该没坏,因为直接对表A或B进行关于X的查询(如select * from a where x=555555),速度始终是很快的,我想如果我有50个人,把B表的500条记录给分了,一人10条,手工到A表查出其正确的Y值,再update回B表,也用不了几分钟(对B的update也是很快的,毕竟只有几百条记录么)。因此我一开始怀疑系统按最慢的一种方案走:从几百万的A表里取出记录一条条到B表比对。我就做了一个存储过程,里面定义一个游标,从B表取出记录,一条条到A表比较,到A表里找出与X对应的正确的Y值,再更新回B表。结果还是很慢,系统始终在做select,我一看,这个进程在对A做全表扫描,就是说索引根本没起作用,要对A表做几百次全表扫描当然快不了。怪了,为什么同样的语句在客户端执行索引有用,在存储过程的游标里不行呢?
不过几百条的更新毕竟是小事,可这两天我在更新两个比较大的表,一个有20000条记录,一个有8000条,开始两个表无论用UPDATE还是我那个存储过程(游标也慢,不过不锁表,我可以看到已经有多少记录被刷新,要是在PB或ADVANTAGE上,不晓得要过二十分钟还是二十个小时才能结束)都慢得让人无法忍受,不过我觉得也许将两个表关联起来select会比update快一点?就执行了如下语句:
select dhhm,jjxbh,jdxh,jx_t_jjd.jjdbh from jx_t_jjd,yi_jjx where jx_t_jjd.jjdbh=yi_jjx.jjdbh; 这里jx_t_jjd 有几百万条记录,相当于前面的A表,yi-jjx相当于B表,不过这回是两万条记录。
很快就出结果了,这样我也得到了X字段和Y字段的正确的对应关系。用showplan看动作如下:
QUERY PLAN FOR STATEMENT 1 (at line 1).
STEP 1
The type of query is INSERT.
The update mode is direct.
Worktable1 created for REFORMATTING.
FROM TABLE
yi_jjx
Nested iteration.
Table Scan.
Forward scan.
Positioning at start of table.
Using I/O Size 16 Kbytes for data pages.
With LRU Buffer Replacement Strategy for data pages.
TO TABLE
Worktable1.
STEP 2
The type of query is SELECT.
FROM TABLE
jx_t_jjd
Nested iteration.
Table Scan.
Forward scan.
Positioning at start of table.
Using I/O Size 16 Kbytes for data pages.
With LRU Buffer Replacement Strategy for data pages.
FROM TABLE
Worktable1.
Nested iteration.
Using Clustered Index.
Forward scan.
Positioning by key.
Using I/O Size 16 Kbytes for data pages.
With LRU Buffer Replacement Strategy for data pages.
(return status = 0)
我也不知道它都做了些啥,不过显然它使用聚簇索引了,这是能够很快得出结果的原因吧。
再对那个8000条记录的表yi_fxh也执行类似语句:select dhhm,a.fxhbh,a.fxhxx,b.fjd from jx_t_fxhjd a,yi_fxh b where a.fjdbh=b.fjd (jx_t_fxhjd相当于前面说的几百万条记录的表A,yi_fxh为表B,不过它有8000条记录) 速度和前者完全不能相比,showplan动作如下:
STEP 1
The type of query is SELECT.
FROM TABLE
yi_fxh
b
Nested iteration.
Table Scan.
Forward scan.
Positioning at start of table.
Using I/O Size 16 Kbytes for data pages.
With LRU Buffer Replacement Strategy for data pages.
FROM TABLE
jx_t_fxhjd
a
Nested iteration.
Table Scan.
Forward scan.
Positioning at start of table.
Using I/O Size 16 Kbytes for data pages.
With LRU Buffer Replacement Strategy for data pages.
(return status = 0)
它在做全表扫描,可这个jx_t_fxhjd是以fjdbh为主键的啊。哭笑不得的是如果我把前面那个看起来挺正常的语句中要检索的字段换成*,也就是select * from jx_t_jjd,yi_jjx where jx_t_jjd.jjdbh=yi_jjx.jjdbh;那它也变成全表扫描了,奇慢无比。FAINT。不过好在这个表我只要其中几个字段,也就算了。
我对这个jx_t_fxhjd表做了update statistics,没用,删除主键重建(当然也在jjdbh上重建了聚促唯一索引),顺便把yi_fxh的索引也重建了,又做了更新统计,还是没用。绝望,只好让它自己慢慢地刷。从早上到现在,大概有三四千条记录被处理过了。也许到明天早上就能都处理完了吧。不知哪位高手能解答我的疑惑。 |
|