这是一个简单的问题。假设我有一个巨大的表(500万行),我别无选择,只能进行完整的表扫描。
SELECT * FROM Table1
有什么方法可以让我的数据库更快地返回结果吗?
背景:
我们有一个由第三方提供给我们的应用程序,它的设计是健壮/灵活的——它的数据库中很少有大表。例如,其中一个表是"Object"表,它存储所有对象。另一个表是"关系"表,它捕获对象之间的所有关系。它本质上允许您在不更改其模式的情况下存储任何内容。
我的任务是设计一个单独的报告应用程序——一个查询该数据库的应用程序。它必须是实时数据。由于表的大小,再加上查询的复杂性,存在性能问题。
我想知道该如何处理性能问题。我已经创建了一个又一个索引,但查询仍然非常复杂,最终,我仍然需要进行多次完整表扫描。
好消息是,我仍处于设计阶段,所以我希望听到尽可能多的建议,以防我错过了什么。
至少有9种方法可以改进全表扫描。但是,改进全表扫描可能不一定能提高整体性能,具体取决于对数据的处理。例如,如果有500万行被发送到一个应用程序,那么网络将成为瓶颈,改进全表扫描也无济于事。
其中一些方法是极端的,可能只在极少数情况下有帮助,并且可能只会略微提高性能。在应用深奥的调优思想之前,请仔细考虑。在花大量时间做一些可能只会将性能提高1%的事情之前,请确保完整的表扫描是瓶颈。
-
并行性
SELECT /*+ PARALLEL */ * FROM Table1;
在许多系统上,并行性可以轻松地将全表扫描性能提高一个数量级。但也有许多限制——合理的配置、大的表大小、仅限企业版等等 - DB_FILE_MULTIBLOCK_READ_COUNT此参数控制一次读取的块数。对于全表扫描,通常越多越好。这个参数很复杂,而且经常被误解。只要它被设置为默认值,那么它可能是最优的
- 硬件有很多方法可以提高磁盘性能。SSD、不同的RAID选项、更快的磁盘、更多的磁盘等
- 增加内存通过增加内存量来缓存更多的表块,特别是缓冲区缓存,它是SGA的一部分。这可能意味着增加MEMORY_TARGET或SGA_TARGET的大小
-
收缩表如果表是只读的,请将其设置为
PCTFREE 0
,以节省为更改而保存的正常10%的空间。此外,如果表在过去发生了很大变化,ALTER TABLE MY_TABLE MOVE;
将重新组织它,并可能填补一些空白。缩小表的物理大小可能会使其读取速度更快 - 减少其他活动检查数据库和服务器上的其他数据库是否有其他活动。可能还有其他进程会占用一些资源
- 压缩使用不同类型的压缩可以显著缩小某些表。这是I/O和CPU之间的权衡。通常,解压缩数据所花费的时间少于检索更多块所花费的额外时间
-
统一扩展区管理默认情况下的自动分配可能会浪费一小部分空间。使用小而均匀的尺寸,可以节省少量空间。或者,如果表有许多小分区,可能会有很大的空间。
CREATE TABLESPACE ... EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
- 增加块大小在极少数情况下,较大的块大小可以提高压缩,减少行链接,并使用较少的块开销
您可以使用并行提示使用并行线程更快地读取整个表。
SELECT /*+ parallel(t 4) */ * FROM Table1 t;
在空闲数据库上,您可以在每个实例上定义并行度,最多可达cpu/内核的数量。