【发布时间】:2010-07-02 12:15:37
【问题描述】:
我正在使用 oracle 9.2.0.3.0 服务器上的新旧数据库。
对新数据库中表的查询比对旧数据库中表的相同查询慢大约 300 倍。
这些数据库非常相似,但也有一些区别:
我在旧表中测试的表有一个 CHAR 列(索引)和 12 个 NUMBER 列。 我在新表中测试的表有一个 NUMBER 列(索引)而不是 CHAR 列、13 个 NUMBER 列和 10 个新的 VARCHAR2 列,大小限制为 40-100。 两个表的索引方式相同(除了列的类型...)
两个表都有大约 1900000 条记录。 我的查询在两种情况下都得到了相同的执行计划(使用了索引,没有全扫描) 数据库在不同的表空间中,但在同一个磁盘上。 旧表空间的使用率约为 70%,新表空间的使用率为 94%,否则设置相同(据我所知)。 表空间内的碎片还不错,但旧的更糟(是的!) 由于新表的列更多,因此它使用的块是旧表的三倍。
关于如何进行的任何想法?
更新 1: 在新数据库上运行 10 次查询后,速度下降到大约 80 倍。改进!然而仍然没有解决。
更新 2: 由于列类型更改,查询确实略有不同。首先是旧的(快),然后是新的(慢 80-300 倍)。
SELECT fhin, SUM(cost)
FROM olddb.oldtable
WHERE month in ('1004 ') AND fhin IN ('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '22', '23', '24', '25', '26', '27', '28', '29', '30', '40', '99')
GROUP BY fhin
SELECT fhin, SUM(cost)
FROM newdb.newtable
WHERE month IN (201004) AND fhin IN ('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '22', '23', '24', '25', '26', '27', '28', '29', '30', '40', '99')
GROUP BY fhin;
请不要问为什么查询看起来像这样,它不是我的;-)
更新 3: 用旧查询解释统计信息:
execution schema (my translation to English)
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (GROUP BY)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'OLDTABLE'
3 2 INDEX (RANGE SCAN) OF 'OLDTABLE' (NON-UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
182 consistent gets
101 physical reads
0 redo size
903 bytes sent via SQL*Net to client
398 bytes received via SQL*Net from client
3 SQL*Net round trips to/from client
1 sorts (memory)
0 sorts (disk)
28 rows processed
解释新查询的统计信息:
execution schema (my translation)
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=36 Card=30 Bytes=360)
1 0 SORT (GROUP BY) (Cost=36 Card=30 Bytes=360)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'NEWTABLE' (Cost=11 Card=13857 Bytes=166284)
3 2 INDEX (RANGE SCAN) OF 'NEWTABLE' (NON-UNIQUE) (Cost=1 Card=22502)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
11019 consistent gets
11018 physical reads
0 redo size
906 bytes sent via SQL*Net to client
398 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
28 rows processed
我猜他们毕竟不是那么相似。有什么想法吗?
更新 4: 感谢您提供的所有出色帮助!问题仍未解决,但我的客户在接下来的两周内无法联系。届时我会尝试一切并返回这里进行进一步的更新!
更新 5:我又回来了!我运行了 A. Musch 建议的聚类因子分析,发现:
Table Clustering Factor Rows Blocks
Old 12633 1930000 12645
New 938379 1890000 39677
我猜问题是我们在新数据库中有一个错误的集群因素。有关如何解决此问题的任何想法或链接?
更新 6:感谢 Adam 的提示,我找到了这篇关于 Oracle B-tree 索引和集群因子 http://richardfoote.files.wordpress.com/2007/12/index-internals-rebuilding-the-truth.pdf 的文章,并按照说明通过按索引列重新排序表来优化集群因子.问题解决了!
【问题讨论】:
-
请在两个数据库中发布相关查询的 tkprof。
-
我不确定我知道该怎么做,但我会试一试!
-
好吧,如果我没记错的话,tkprof 需要访问服务器的命令提示符。我在一个环境非常封闭的客户那里参加了一次非常短暂的演出。我什至无法访问本地命令提示符。叹息..
-
@8DH:是的,您需要访问服务器才能检索跟踪文件。我要求提供 tkprof,因为它是确定正在使用的实际执行计划的最佳方法之一。如果您无权访问服务器,请使用 SQL*PLUS SET AUTOTRACE TRACEONLY EXPLAIN STATISTICS 的输出发布一个相关查询(在两个数据库中)
-
@Alex Poole:不,两种情况都不是。月份列上只有一个索引。
标签: performance oracle