Oracle 首选列长度

标签 oracle database-design database-performance

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

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

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


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

我们是否应该总是尝试将列的长度设置为 2 的某个幂?还是只有最大尺寸很重要?

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

最佳答案

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

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

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

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

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

编辑 2 :

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

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

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

两个表都正好有 1048576 行。

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

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

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

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

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

查询>

所以两个表的全表扫描完全一样。那么当我们实际选择数据时会发生什么呢?

SQL> select * from wide;

已选择 1048576 行。

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

SQL> select * from 窄;

已选择 1048576 行。

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

查询>

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

关于Oracle 首选列长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14375250/

相关文章:

mysql - 我如何创建一个高效的 MySQL 数据库来自动完成像谷歌这样的请求

java - Spring在JDBCTemplate中对异常处理的实现

oracle - BULK COLLECT 的奇怪行为

node.js - 如何向 MongoDB 中的单个模型添加 2 个引用?

postgresql - 相等值和相反值的 SQL 查询

python - Django 预取与最大值过滤器相关

sql - 可以禁用 Oracle 中的 SQL 执行计划吗?

java - 如何使用单个 order by 子句在 jOOQ 中编写联合查询?

sql - SELECT 子句使用 IN ... 很慢?

MySQL - 使用复合模式设置外键(将多个表映射到一个映射)