我们如何优化oracle数据库呢?

发布于 2024-09-28 14:33:06 字数 4266 浏览 4 评论 0原文

我们有一个 Oracle 9i 数据库,其中有 7 个表,每个表都有 15+ 百万条记录。表之间没有关系,即没有外键。

以下是其中一张表的示例

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。这样做会是疯狂的事情吗?我想知道。

我们迭代 inserv 的数量并对它们运行所有查询。目前我们正在清除数据,因此我们预计不会超过 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来将整个数据库加载到内存中。用ORACLE可以做到吗?

提前致谢

We have a Oracle 9i Database with 7 tables each with 15+ Million records. There is no relation between the table i.e. no foreign keys.

Here is an example of one of the tables

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
)

Note that INSERVID can be one of the 1400 types. So it's possible to have say 1400 tables each dedicated to one inserv. Would that be insane thing to do ? I wonder.

We iterate over the no of inservs and run all our queries against them. Right now we are purging data so we don't expect to overshoot 15+ million records.

1) We have distinct in the queries so it takes full table scan. Oracle Execution plan shows we are doing quite full table scan.

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) Every table has an index on inserv id. It has helped in reducing the cost of queries, what can we do further ? Any tips/tricks to make things faster ?

3) Does it make sense if we make our sql queries that run against each table as parallel scripts running against each table. Would this result in faster completion ?

4) We have enough RAM to load the whole DB in memory. Is it possible to do that with ORACLE.

Thanks in Advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冷︶言冷语的世界 2024-10-05 14:33:06

1-2) 在 (inservid,commandtimestamp) 上建立索引将用(快速)完整索引扫描替换完整表扫描,因为两列之一不为空(因此数据库可以使用索引而不是表)。这应该比全表扫描更快,但所有 15+ M 行索引条目都将被读取。

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

3)如果您还有一些 IO 带宽,并行运行的查询会给您带来一些好处。现在,您的全表扫描可能会从磁盘读取大量行。除非您的表驻留在物理上分离的设备上,否则并行的收益将是最小的。

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

1-2) Having an index on (inservid,commandtimestamp) will replace the FULL TABLE SCAN with a (FAST) FULL INDEX SCAN since one of the two columns is NOT NULL (hence the DB can use the index instead of the table). This should be faster than the full table scan but all 15+ M rows index entries will be read.

You could get a faster response time with a precomputed table (for example a Fast Refresh Materialized View), in that case you will probably take a performance hit on DML operations on the table (insert/update/delete will be slower)

3) Having the queries run in parallel will give you some benefit if you have some IO bandwidth left. Right now your full table scan will probably read a lot of rows from the disks. Unless your tables reside on physically separated devices, the gain by going parallel will be minimal.

4) loading in RAM is mainly done automatically in Oracle: i.e. in most case Oracle does a good job in placing frequently accessed data in memory.

耳钉梦 2024-10-05 14:33:06

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

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

摘自 Oracle® 数据库性能调优指南
11g 版本 2 (11.2) 部件号 E16638-03

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

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

替代文本

Part 4, this is usually not nececary. In 9i you can setup a special "keep" buffer pool to try to keep your indexes in memory. (but since there is no support avaliable from Oracle now, it might not be a good time to start experimenting with features you have not used so far)

Are your clients on the local machine, if not the client may benefit from the 11g feature Client (side" result cache, to minimize database server round trips.

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

7.6.2.1 How the Client Result Cache Works
The client result cache stores the results of the outermost query, which are the columns defined by the OCI application. Subqueries and query blocks are not cached.

Figure 7-4 shows a client process with a database login session. This client process has one client result cache shared among multiple application sessions running in the client process. If the first application session runs a query, then it retrieves rows from the database and caches them in the client result cache. If other application sessions run the same query, then they also retrieve rows from the client result cache.

alt text

静若繁花 2024-10-05 14:33:06

1),4) 我同意文森特的观点。

2)你有很长的行 - 所以最好有一个更大的 db_block_size - 16Kb 或 32Kb
也许值得尝试在你的桌子上进行压缩。还要检查您的 db_file_multiblock_read_count。可以对其进行分区 - 将其分发到尽可能多的驱动器上。

3)你可以玩一下并行提示,看看效果如何。

by 1),4) i agree with Vincent.

by 2) you have a long rows - so it may be good to have a bigger db_block_size - 16Kb or 32Kb
and it may be worth to try compress on your table. also check your db_file_multiblock_read_count. may be partiton it - distribute it on as many drives as you have.

3) you can play with parallel hint to see how it would be.

输什么也不输骨气 2024-10-05 14:33:06

您的数据模型已损坏。您能否提供有关您运行的查询的更多详细信息?添加索引只能在一定程度上帮助您。

Your data model is broken. Can you provide more detail on the queries you run? Adding indexes will only help you to a point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文