惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
量子位
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
GbyAI
GbyAI
爱范儿
爱范儿
Y
Y Combinator Blog
宝玉的分享
宝玉的分享
有赞技术团队
有赞技术团队
罗磊的独立博客
Recent Announcements
Recent Announcements
博客园 - 司徒正美
M
MIT News - Artificial intelligence
小众软件
小众软件
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
B
Blog RSS Feed
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research
雷峰网
雷峰网

博客园 - badog

SQL Server 中的模糊查询 LIKE JavaScript中引号的嵌套 - badog - 博客园 全国各地讨老婆成本一览 去上海滑雪 好像最近买了很多东西 雁荡山小记 Google搜索引擎使用技巧2005版 - badog - 博客园 一道引起全美大学生和很多军械学院人士举论坛辩论的逻辑题 (大家轻松一下) LV手纸 编写多线程程序时碰到的一些问题 我的人格类型是: ISTJ (内向,感觉,思维,判断) Visual Studio .net 默认编码问题 Invoke的TargetInvocationException问题 吃饭 中秋节的日记 阶段总结(1) 阶段总结 看了一天小说 买东西
SQL Server 中 nchar和nvchar的性能差距
badog · 2006-02-05 · via 博客园 - badog

 顺手测试了一下SQL Server2000中的情况

SQL Server 中 nchar和nvchar的性能差距(执行时间)

联机丛书中的说明

使用 char 和 varchar 数据

char varchar 数据类型的数据包括:

  • 大写字母或小写字母,比如 a、b 和 C。
  • 数字,比如 1,2 或 3。
  • 特殊字符,如 at 符号 (@)、"与"符号 (&) 和惊叹号 (!)。

char varchar 数据可以是单个字符,或者是最长可达 8,000 个字符的字符串。

每个 charvarchar 数据值都有排序规则。排序规则定义特性,如用于表示每个字符的位模式、比较规则以及是否区分大小写或重音。每个数据库有默认排序规则。当定义列或指定常量时,除非使用 COLLATE 子句指派特定的排序规则,否则将为它们指派数据库的默认排序规则。当合并或比较两个具有不同排序规则的 charvarchar 值时,排序规则的优先顺序规则决定操作所使用的排序规则。

字符常量必须包括在单引号 (') 或双引号 (") 中。建议用单引号括住字符常量。当 QUOTED IDENTIFIER 选项设为 ON 时,有时不允许用双引号括住字符常量。

这个 Transact-SQL 例子给一个字符变量赋值:

DECLARE @MyCharVar CHAR(25)
SET @MyCharVar = 'Ricardo Adocicados'

当使用单引号分隔一个包括嵌入单引号的字符常量时,用两个单引号表示嵌入单引号,例如:

SET @MyCharVar = 'O''Leary'

如果要存储的数据比允许的字符数多,则数据就会被截断。例如,如果某列被定义为 char(10) 并且值"This is a really long character string"被存储到该列中,则 Microsoft® SQL Server™ 将该字符串截断为"This is a"。

当指定了 NOT NULL 子句时,char 数据类型是固定长度数据类型。如果一个比列的长度小的值被插入到 char NOT NULL 列中,则值的右边以空格填补剩余的位置。例如,如果一个列被定义为 char(10) 并且要存储的数据是"music",则 SQL Server 将这个数据存储为"music_____",这里"_"表示空格。

当创建一个 char NULL 列时,如果 ANSI_PADDING 是ON,它的表现就如同一个 char NOT NULL列:值的右边按照列的大小进行填补。当创建一个 char NULL 列时,如果 ANSI_PADDING 是 OFF,它的表现就如同一个将 ANSI_PADDING 设置为 OFF 的 varchar 列:尾随空格将被截断。

varchar 是可变长度的数据类型。比列的长度小的值,不会按照列的长度在其右边填补。当创建列时,如果 ANSI_PADDING 选项设为 OFF,则所有存储在列中的字符值的尾随空格都将被截断。当创建列时,如果 ANSI_PADDING 设为 ON,则尾随空格不被截断。

CHAR 函数可以把一个整数转换为 ASCII 字符。当确定控制字符时(比如回车或换行),这是很有用的。在字符串中用 CHAR(13) 和 CHAR(10) 产生一个回车并生成一个新行。

PRINT 'First line.' + CHAR(13) + CHAR(10) + 'Second line.'

一个字符串的字节中位的存储格式是按照安装时所指定的 Microsoft SQL Server 代码页来解释的。一个 char varchar 对象可以包含 SQL Server 代码页中的任何字符。有关更多信息,请参见排序规则。

DB-Library 应用程序和使用来自 SQL Server 6.5 版或更早版本的 SQL Server ODBC 驱动程序的应用程序最多仅支持 255 个字节的字符数据。如果这些应用程序尝试检索 SQL Server 7.0 版或更新版本的字符参数或包含超过 255 个字节的数据的结果集,字符数据将在 255 个字节处截断。

1. 实际存储的字符串长度和字段类型最大长度相同

create table test(a nchar(20))
create table testv(a nvarchar(20))

insert

declare @loop  int
set @loop=0
while @loop<5000
begin
 insert into test values('aaaaaaaaaaaaaaaaaaaa')
 set @loop=@loop+1
end

用时00:31

declare @loop  int
set @loop=0
while @loop<5000
begin
 insert into testv values('aaaaaaaaaaaaaaaaaaaa')
 set @loop=@loop+1
end

用时00:32

update

declare @loop  int
set @loop=0
while @loop<1000
begin
 update test set a='11111111111111111111'
 set @loop=@loop+1
end

用时00:48

declare @loop  int
set @loop=0
while @loop<1000
begin
 update testv set a='11111111111111111111'
 set @loop=@loop+1
end

用时00:54

declare @loop  int
set @loop=0
while @loop<1000
begin
 update testv set a='aaaaaaaaaaaaaaaaaaaa' where  a='aaaaaaaaaaaaaaaaaaaa'
 set @loop=@loop+1
end

用时01:12

declare @loop  int
set @loop=0
while @loop<1000
begin
 update test set a='aaaaaaaaaaaaaaaaaaaa' where  a='aaaaaaaaaaaaaaaaaaaa'
 set @loop=@loop+1
end

用时01:12

select

declare @loop  int
set @loop=0
while @loop<1000
begin
 select * from testv
 set @loop=@loop+1
end

用时01:15

declare @loop  int
set @loop=0
while @loop<1000
begin
 select * from test
 set @loop=@loop+1
end

用时01:15

declare @loop  int
set @loop=0
while @loop<1000
begin
 select * from test where  a='aaaaaaaaaaaaaaaaaaaa'
 set @loop=@loop+1
end

用时01:27

declare @loop  int
set @loop=0
while @loop<1000
begin
 select * from testv where  a='aaaaaaaaaaaaaaaaaaaa'
 set @loop=@loop+1
end

用时01:31

2. 实际存储的字符串长度小于字段类型最大长度

※ 节省存储空间
※ 插入、更新快
※ 查询的时候节省DB与Web服务器之间的传输量以及物理I/O
※ 对于UPDATE改变数据的长度,char的存储空间不发生变化,而VARCHAR2的存储空间会发生变化

create table test(a nchar(2000))
create table testv(a nvarchar(2000))

insert

declare @loop  int
set @loop=0
while @loop<10000
begin
 insert into test values('aaaaaaaaaa')
 set @loop=@loop+1
end

用时01:14

declare @loop  int
set @loop=0
while @loop<10000
begin
 insert into test values('aaaaaaaaaa')
 set @loop=@loop+1
end

用时01:04

 这里差距还不大

select

declare @loop  int
set @loop=0
while @loop<100
begin
 select * from testv
 set @loop=@loop+1
end
用时00:13

declare @loop  int
set @loop=0
while @loop<10
begin
 select * from test
 set @loop=@loop+1
end

用时01:20

 这里就看出差距了(当然我是故意把栏位设定的很大来突出差距)

update

declare @loop  int
set @loop=0
while @loop<10
begin
 update test set a='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' where a='aaaaaaaaaa'
 update test set a='aaaaaaaaaa' where a='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
 set @loop=@loop+1
end

用时00:58

declare @loop  int
set @loop=0
while @loop<10
begin
 update testv set a='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' where a='aaaaaaaaaa'
 update testv set a='aaaaaaaaaa' where a='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
 set @loop=@loop+1
end

用时00:19

3查询条件中空格的进一步研究

test 及testv中均为''aaaaaaaaaa'

select * from testv where a='aaaaaaaaaa   '
select * from test where a='aaaaaaaaaa      '

都可以查到结果,与开头连接中Oracle不同,应该是在select之前自动先trim了