在这个答案(/programming/517579/strings-as-primary-keys-in-sql-database)中,有一条话引起了我的注意:
还请记住,进行索引比较时,CHAR和VARCHAR之间通常会有很大的差异
这是否适用/仍适用于Postgres?
我发现Oracle上的页面声称CHAR
或多或少是别名VARCHAR
,因此索引性能是相同的,但是在Postgres上没有确定的定义。
在这个答案(/programming/517579/strings-as-primary-keys-in-sql-database)中,有一条话引起了我的注意:
还请记住,进行索引比较时,CHAR和VARCHAR之间通常会有很大的差异
这是否适用/仍适用于Postgres?
我发现Oracle上的页面声称CHAR
或多或少是别名VARCHAR
,因此索引性能是相同的,但是在Postgres上没有确定的定义。
Answers:
CHAR
并且VARCHAR
在Postgres(和Oracle)中实现的方式完全相同。使用这些数据类型时,速度没有差异。
但是,有一个差异可以影响性能:char
列始终填充为定义的长度。因此,如果将一列定义为char(100)
和,varchar(100)
但每个char(100)
列仅存储10个字符,则该列将为每个值使用100个字符(存储的10个字符加上90个空格),而该varchar
列仅存储10个字符。
将100个字符与100个字符进行比较将比将10个字符与10个字符进行比较要慢-尽管我怀疑您实际上可以在SQL查询中测量这种差异。
如果同时声明两个字符的长度都为10个字符,并且始终在其中恰好存储10个字符,那么绝对没有区别(对于Oracle和Postgres都是如此)
因此,唯一的区别是对char
数据类型执行的填充。
还请记住,进行索引比较时,CHAR和VARCHAR之间通常会有很大的差异
仅当(且仅当)char
列定义得太宽(即,由于填充而浪费空间)时,以上引用才适用。如果该char
列的长度始终被完全使用(因此不会出现填充),那么以上引用是错误的(至少对于Postgres和Oracle而言)
从我的角度来看,char
数据类型实际上并没有任何实字用法。只是使用varchar
(或text
在Postgres中)而忘记了它的char
存在。
我同意a_horse_with_no_name 所说的一切,而且我通常也同意Erwin的评论建议:
不,char是劣等的(并且已过时)。text和varchar的执行(几乎)相同。
除了一个较小的例外,我唯一使用的时间char()
是当我希望元数据说必须具有x字符时。尽管我知道char()
只有在输入超出限制时才会抱怨,但我会经常防止CHECK
约束中的欠载。例如,
CREATE TABLE foo (
x char(10) CHECK ( length(x) = 10 )
);
INSERT INTO foo VALUES (repeat('x', 9));
我这样做有几个原因,
char(x)
有时使用模式加载器将其推断为固定宽度的列。这可能会对为固定宽度字符串优化的语言有所不同。需要一个我可以在哪里做的例子,
ENUM
。请注意,某些人可能对限制两侧的错误消息不一致感到不安,但这并没有打扰我
test=# INSERT INTO foo VALUES (repeat('x', 9));
ERROR: new row for relation "foo" violates check constraint "foo_x_check"
DETAIL: Failing row contains (xxxxxxxxx ).
test=# INSERT INTO foo VALUES (repeat('x', 11));
ERROR: value too long for type character(10)
varchar
而且,我认为上述建议与几乎总是使用text
的约定非常吻合。你也问varchar(n)
。我从不使用。至少,我不记得上一次使用varchar(n)
。
char(n)
,text
有效varchar
(无限制)的方法如果我发现规范中包含有意义的可变长度文本键,并且相信可以拥有恒定的最大长度,那么我也会使用varchar(n)
。但是,我想不出符合该标准的任何东西。
char
这里不要混淆,"char"
它是一种单字节类型,具有可靠的性能和节省空间的优点。相关问答:
PostgreSQL
sales_reporting_db=# create table x (y char(2));
CREATE TABLE
sales_reporting_db=# insert into x values ('Y');
INSERT 0 1
sales_reporting_db=# select '*' || y || '*' from x;
?column?
----------
*Y*
甲骨文
SQL> create table x ( y char(2));
Table created.
SQL> insert into x values ('Y');
1 row created.
SQL> select '*' || y || '*' from x;
'*'|
----
*Y *
PostgreSQL没有用空格填充。
SELECT pg_column_size(y) FROM x;
我发现这最有用,并且有3行快速解释:
从CHAR(n)VS VARCHAR(N)VS Postgres中的文本
- 如果要存储一些长度未知的文本,请使用
TEXT
数据类型。- 如果要存储一些长度未知的文本,但知道最大长度,请使用
VARCHAR(n)
。- 如果您要存储一些确切长度已知的文本,请使用
CHAR(N)
。