我们如何优化oracle数据库?

时间:2010-10-21 11:53:53

标签: database oracle database-design oracle9i

我们有一个Oracle 9i数据库,其中包含7个表,每个表有1500多万条记录。表之间没有关系,即没有外键。

以下是其中一个表

的示例
CREATE TABLE GSS.SHOWPD
(
  INSERVID          VARCHAR2(7 CHAR)            NOT NULL,
  CAGEPOS           VARCHAR2(8 CHAR)            DEFAULT NULL,
  DETAILEDSTATE     VARCHAR2(100 CHAR)          DEFAULT NULL,
  FAILEDMB          NUMBER                      DEFAULT NULL,
  FREECHUNK         NUMBER                      DEFAULT NULL,
  FREEMB            NUMBER                      DEFAULT NULL,
  FWREV             VARCHAR2(100 CHAR)          DEFAULT NULL,
  FWSTATUS          VARCHAR2(100 CHAR)          DEFAULT NULL,
  AID               NUMBER                      DEFAULT NULL,
  LDA               VARCHAR2(100 CHAR)          DEFAULT NULL,
  MANUF             VARCHAR2(100 CHAR)          DEFAULT NULL,
  AMODEL            VARCHAR2(4000 CHAR)         DEFAULT NULL,
  NODEWWN           VARCHAR2(64 CHAR)           DEFAULT NULL,
  NRMUNUSEDFAIL     VARCHAR2(100 CHAR)          DEFAULT NULL,
  NRMUNUSEDFREE     VARCHAR2(100 CHAR)          DEFAULT NULL,
  NRMUNUSEDUNAVAIL  VARCHAR2(100 CHAR)          DEFAULT NULL,
  NRMUSEDFAIL       VARCHAR2(100 CHAR)          DEFAULT NULL,
  NRMUSEDOK         VARCHAR2(100 CHAR)          DEFAULT NULL,
  AORDER            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PATHA0            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PATHA1            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PATHB0            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PATHB1            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PORTA0            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PORTA1            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PORTB0            VARCHAR2(100 CHAR)          DEFAULT NULL,
  PORTB1            VARCHAR2(100 CHAR)          DEFAULT NULL,
  RDCERR            VARCHAR2(100 CHAR)          DEFAULT NULL,
  REUERR            VARCHAR2(100 CHAR)          DEFAULT NULL,
  SERIAL            VARCHAR2(100 CHAR)          DEFAULT NULL,
  SIZEMB            NUMBER                      DEFAULT NULL,
  SPARECHUNK        VARCHAR2(100 CHAR)          DEFAULT NULL,
  SPAREMB           NUMBER                      DEFAULT NULL,
  SPEEDKRPM         VARCHAR2(100 CHAR)          DEFAULT NULL,
  SPRUNUSEDFAIL     VARCHAR2(100 CHAR)          DEFAULT NULL,
  SPRUNUSEDFREE     VARCHAR2(100 CHAR)          DEFAULT NULL,
  SPRUNUSEDUNINIT   VARCHAR2(100 CHAR)          DEFAULT NULL,
  SPRUSEDFAIL       VARCHAR2(100 CHAR)          DEFAULT NULL,
  SPRUNUSEDOK       VARCHAR2(100 CHAR)          DEFAULT NULL,
  STATE             VARCHAR2(100 CHAR)          DEFAULT NULL,
  TEMPDEGC          NUMBER                      DEFAULT NULL,
  TOTALCHUNK        VARCHAR2(100 CHAR)          DEFAULT NULL,
  ATYPE             VARCHAR2(100 CHAR)          DEFAULT NULL,
  UNAVAILABLEMB     NUMBER                      DEFAULT NULL,
  VOLUMEMB          NUMBER                      DEFAULT NULL,
  WRCERR            VARCHAR2(100 CHAR)          DEFAULT NULL,
  WRUERR            VARCHAR2(100 CHAR)          DEFAULT NULL,
  COMMANDTIMESTAMP  TIMESTAMP(6)                DEFAULT NULL  NOT NULL,
  FETCHTIMESTAMP    TIMESTAMP(6)                DEFAULT NULL  NOT NULL
)

请注意,INSERVID可以是1400种类型之一。因此,有可能说1400个表,每个表专用于一个inserv。那会是疯狂的事吗?我不知道。

我们迭代了inservs并对它们运行所有查询。目前我们正在清除数据,因此我们预计不会超过1500万条记录。

1)我们在查询中有所区别,因此需要全表扫描。 Oracle执行计划显示我们正在进行全面的表扫描。

select distinct(inservid),commandtimestamp from statpd order by commandtimestamp desc;

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |   665 | 13300 | 79488 |
|   1 |  SORT UNIQUE         |             |   665 | 13300 | 69088 |
|   2 |   TABLE ACCESS FULL  | STATPD      |  4128K|    78M| 19406 |
--------------------------------------------------------------------
Note: cpu costing is off
10 rows selected.

2)每个表都有一个inserv id的索引。它有助于降低查询成本,我们还能做些什么呢?任何使事情变得更快的提示/技巧?

3)如果我们将针对每个表运行的sql查询作为针对每个表运行的并行脚本,这是否有意义。这会导致更快完成吗?

4)我们有足够的RAM来将整个DB加载到内存中。是否可以使用ORACLE执行此操作。

先谢谢

4 个答案:

答案 0 :(得分:5)

1-2)索引(inservid,commandtimestamp)将使用(FAST)FULL INDEX SCAN替换FULL TABLE SCAN,因为两列中的一列是NOT NULL(因此DB可以使用索引而不是表)。这应该比全表扫描更快,但将读取所有15 M行索引条目。

使用预先计算的表(例如快速刷新物化视图)可以获得更快的响应时间,在这种情况下,您可能会对表上的DML操作产生性能影响(插入/更新/删除会更慢)

3)如果剩下一些IO带宽,那么并行运行查询会带来一些好处。现在,您的全表扫描可能会从磁盘中读取大量行。除非您的表位于物理上分离的设备上,否则通过并行获得的增益将是最小的。

4)在RAM中加载主要是在Oracle中自动完成的:即在大多数情况下,Oracle在将频繁访问的数据放入内存方面做得很好。

答案 1 :(得分:2)

第4部分,这通常不是必要的。在9i中,您可以设置一个特殊的“保持”缓冲池,以尝试将索引保留在内存中。 (但由于现在没有Oracle提供的支持,现在可能不是开始尝试迄今为止尚未使用的功能的好时机)

您的客户端是否在本地计算机上,如果不是客户端可能会受益于11g功能客户端(侧面“结果缓存,以最小化数据库服务器往返。

Excerpt from Oracle® Database Performance Tuning Guide 11g Release 2 (11.2) Part Number E16638-03

  

7.6.2.1客户端结果缓存的工作原理   客户端结果缓存存储最外层查询的结果,这些查询是OCI应用程序定义的列。不缓存子查询和查询块。

     

图7-4显示了具有数据库登录会话的客户端进程。此客户端进程在客户端进程中运行的多个应用程序会话之间共享一个客户端结果缓存。如果第一个应用程序会话运行查询,则它从数据库中检索行并将它们缓存在客户端结果缓存中。如果其他应用程序会话运行相同的查询,则它们还从客户端结果缓存中检索行。

alt text

答案 2 :(得分:1)

1),4)我同意文森特。

2)你有一个很长的行 - 所以有一个更大的db_block_size - 16Kb或32Kb可能会更好 并且可能值得尝试压缩你的桌子。还要检查你的db_file_multiblock_read_count。可能是它的分区 - 将它分配到你拥有的驱动器上。

3)你可以使用平行提示来查看它是怎样的。

答案 3 :(得分:0)

您的数据模型已损坏。您能否提供有关您运行的查询的更多详细信息?添加索引只会帮助您达到目的。