7

列长度​​的乘数是否会以某种方式影响数据库性能?

换句话说,以下两个表的性能有什么区别:

TBL1:
  - CLMN1 VARCHAR2(63)
  - CLMN2 VARCHAR2(129)
  - CLMN3 VARCHAR2(250)

TBL2:
  - CLMN1 VARCHAR2(64)
  - CLMN2 VARCHAR2(128)
  - CLMN3 VARCHAR2(256)

我们应该总是尝试使列的长度达到一定的幂2还是只有最大大小才重要?

一些开发人员声称,数据库中列长度的倍增因子之间存在某种联系,因为它影响 Oracle 如何在磁盘上分配和保存数据以及共享其在内存中的缓存。有人可以证明或反驳这一点吗?

4

1 回答 1

9

性能上没有区别。由于 2 的幂,没有进行任何隐藏的优化。

唯一对事物的存储方式产生影响的是实际数据。存储在VARCHAR2(2000)列中的 100 个字符的存储方式与存储在列中的 100 个字符完全相同VARCHAR2(500)

将长度视为业务约束,而不是数据类型的一部分。唯一应该驱动您决定长度的是关于放入其中的数据的业务限制。

编辑:长度确实有所不同的唯一情况是当您需要该列的索引时。较旧的 Oracle 版本 (< 10) 确实对密钥长度有限制,并且在创建索引时会检查该限制。

尽管在 Oracle 11 中是可能的,但对具有 4000 个字符的值进行索引可能不是最明智的选择。

编辑 2

所以我很好奇并设置了一个简单的测试:

create table narrow (id varchar(40));
create table wide (id varchar(4000));

然后用由 40 个“X”组成的字符串填充两个表。如果存储之间确实存在(实质性)差异,那么在检索数据时应该会以某种方式显示出来,对吧?

两个表都有 1048576 行。

连接到:
Oracle Database 11g 企业版 11.2.0.3.0 - 64 位生产
具有分区、OLAP、数据挖掘和实际应用程序测试选项

SQL> 设置自动跟踪 traceonly 统计信息
SQL> select count(*) from wide;


统计数据
-------------------------------------------------- --------
          0 次递归调用
          1 db 块获取
       6833 一致获得
          0 次物理读取
          0 重做大小
        通过 SQL*Net 向客户端发送 349 个字节
        通过 SQL*Net 从客户端收到 472 个字节
          2 次 SQL*Net 往返客户端
          0 种(内存)
          0 种(磁盘)
          已处理 1 行

SQL> 从窄中选择计数(*);


统计数据
-------------------------------------------------- --------
          0 次递归调用
          1 db 块获取
       6833 一致获得
          0 次物理读取
          0 重做大小
        通过 SQL*Net 向客户端发送 349 个字节
        通过 SQL*Net 从客户端收到 472 个字节
          2 次 SQL*Net 往返客户端
          0 种(内存)
          0 种(磁盘)
          已处理 1 行

SQL>

因此,两个表的全表扫描完全相同。那么当我们实际选择数据时会发生什么?

SQL> 从宽中选择 *;

选择了 1048576 行。


统计数据
-------------------------------------------------- --------
          4个递归调用
          2 db 块获取
      76497 一致获取
          0 次物理读取
          0 重做大小
   54386472 字节通过 SQL*Net 发送到客户端
     通过 SQL*Net 从客户端收到 769427 个字节
      69907 SQL*Net 往返客户端
          0 种(内存)
          0 种(磁盘)
    处理了 1048576 行

SQL> 从窄中选择 *;

选择了 1048576 行。


统计数据
-------------------------------------------------- --------
          4个递归调用
          2 db 块获取
      76485 一致获取
          0 次物理读取
          0 重做大小
   54386472 字节通过 SQL*Net 发送到客户端
     通过 SQL*Net 从客户端收到 769427 个字节
      69907 SQL*Net 往返客户端
          0 种(内存)
          0 种(磁盘)
    处理了 1048576 行

SQL>

一致的获取略有不同,但这可能是由于缓存。

于 2013-01-17T08:58:58.060 回答