我们有一个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执行此操作。
先谢谢
答案 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显示了具有数据库登录会话的客户端进程。此客户端进程在客户端进程中运行的多个应用程序会话之间共享一个客户端结果缓存。如果第一个应用程序会话运行查询,则它从数据库中检索行并将它们缓存在客户端结果缓存中。如果其他应用程序会话运行相同的查询,则它们还从客户端结果缓存中检索行。
答案 2 :(得分:1)
1),4)我同意文森特。
2)你有一个很长的行 - 所以有一个更大的db_block_size - 16Kb或32Kb可能会更好 并且可能值得尝试压缩你的桌子。还要检查你的db_file_multiblock_read_count。可能是它的分区 - 将它分配到你拥有的驱动器上。
3)你可以使用平行提示来查看它是怎样的。
答案 3 :(得分:0)
您的数据模型已损坏。您能否提供有关您运行的查询的更多详细信息?添加索引只会帮助您达到目的。