Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 列的一部分上的SQL索引_Sql Server_Indexing - Fatal编程技术网

Sql server 列的一部分上的SQL索引

Sql server 列的一部分上的SQL索引,sql-server,indexing,Sql Server,Indexing,我有一个包含许多列的大型SQL Server表。我曾尝试优化表以获得最小的存储空间,因为查询并不经常进行 然而,最近我被要求查询这个表以查找特定的GUID 由于空间限制,我不想在GUID上放置索引,因为这将使用许多GB的存储空间 是否有一种方法可以在列上添加索引,但只能在前2个字符上添加索引 这应该足以将数据集减少到足够小的数量,然后进行物理读取?实现了速度和存储空间的混合 简而言之,如果我有一个名为ID的varchar(36)列,我可以只在该列的前两个字符上添加索引吗 create index

我有一个包含许多列的大型SQL Server表。我曾尝试优化表以获得最小的存储空间,因为查询并不经常进行

然而,最近我被要求查询这个表以查找特定的GUID

由于空间限制,我不想在GUID上放置索引,因为这将使用许多GB的存储空间

是否有一种方法可以在列上添加索引,但只能在前2个字符上添加索引

这应该足以将数据集减少到足够小的数量,然后进行物理读取?实现了速度和存储空间的混合

简而言之,如果我有一个名为
ID
varchar(36)
列,我可以只在该列的前两个字符上添加索引吗

create index(2) on ID
如果我有一个名为ID的varchar(36)列,我可以只在该列的前两个字符上添加索引

是的,您可以..这种类型的索引称为计算索引

下面是一些测试数据,以演示如何在其上创建计算列和索引

create table t12
(
id varchar(36)  default CONVERT(varchar(36), NEWID())
)


insert into t12
default values
go 100

--add computed column
alter table t12
add col2 as left(id,2)

--create index
create index nci on t12(col2)

select col2 from t12 where col2='30'-this does a index seek
要在计算列上创建索引,它必须满足一些已解释的属性,您可以检查列是否满足这些属性

SELECT    
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsComputed') AS IsComputed,
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsDeterministic') AS IsDeterministic,
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsPrecise') AS IsPrecise,
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsIndexable') AS IsIndexable
如果
IsPRecise
,则可能需要保留该列,这可能会占用空间

注意:
在大型列上创建计算索引可能需要大量内存进行排序(使用:sort in tempdb选项),并且内存可能不足。我尝试在260亿行数据(历史数据)上创建计算索引,但失败

您的新计算列不唯一

如果我有一个名为ID的varchar(36)列,我可以只在该列的前两个字符上添加索引

是的,您可以..这种类型的索引称为计算索引

下面是一些测试数据,以演示如何在其上创建计算列和索引

create table t12
(
id varchar(36)  default CONVERT(varchar(36), NEWID())
)


insert into t12
default values
go 100

--add computed column
alter table t12
add col2 as left(id,2)

--create index
create index nci on t12(col2)

select col2 from t12 where col2='30'-this does a index seek
要在计算列上创建索引,它必须满足一些已解释的属性,您可以检查列是否满足这些属性

SELECT    
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsComputed') AS IsComputed,
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsDeterministic') AS IsDeterministic,
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsPrecise') AS IsPrecise,
     COLUMNPROPERTY( OBJECT_ID('DBO.t12'), 'col2','IsIndexable') AS IsIndexable
如果
IsPRecise
,则可能需要保留该列,这可能会占用空间

注意:
在大型列上创建计算索引可能需要大量内存进行排序(使用:sort in tempdb选项),并且内存可能不足。我尝试在260亿行数据(历史数据)上创建计算索引,但失败


您的新计算列不是唯一的

您可以索引[int]列而不是varchar(36),并节省两次以上的空间。 下面的示例演示了这一点:

use [tempdb];

if object_id('tempdb..#t1') is not null drop table [#t1];
if object_id('tempdb..#t2') is not null drop table [#t2];

-- create tables
create table [#t1] ([guid] varchar(36), [guid_int] int);
create table [#t2] ([guid] varchar(36), [guid_int] int);
-- dummy data
;with data as (select top  10000 [guid] = newid() from sys.columns t1 cross apply sys.columns t2) insert into [#t1] select [guid], convert(int, convert(binary, [guid])) from [data];
;with data as (select top  10000 [guid] = newid() from sys.columns t1 cross apply sys.columns t2) insert into [#t2] select [guid], convert(int, convert(binary, [guid])) from [data];
-- create indexes
create nonclustered index [ix_#t1_guid]     on [#t1]([guid]);
create nonclustered index [ix_#t2_guid_int] on [#t2]([guid_int]);
-- check space used
exec sp_spaceused N'tempdb..#t1';
exec sp_spaceused N'tempdb..#t2'; 
使用int列而不是varchar(2)您有:
a) 更具唯一性b)int索引大小小于varchar(2)

您可以索引[int]列而不是varchar(36),并节省两倍以上的空间。 下面的示例演示了这一点:

use [tempdb];

if object_id('tempdb..#t1') is not null drop table [#t1];
if object_id('tempdb..#t2') is not null drop table [#t2];

-- create tables
create table [#t1] ([guid] varchar(36), [guid_int] int);
create table [#t2] ([guid] varchar(36), [guid_int] int);
-- dummy data
;with data as (select top  10000 [guid] = newid() from sys.columns t1 cross apply sys.columns t2) insert into [#t1] select [guid], convert(int, convert(binary, [guid])) from [data];
;with data as (select top  10000 [guid] = newid() from sys.columns t1 cross apply sys.columns t2) insert into [#t2] select [guid], convert(int, convert(binary, [guid])) from [data];
-- create indexes
create nonclustered index [ix_#t1_guid]     on [#t1]([guid]);
create nonclustered index [ix_#t2_guid_int] on [#t2]([guid_int]);
-- check space used
exec sp_spaceused N'tempdb..#t1';
exec sp_spaceused N'tempdb..#t2'; 
使用int列而不是varchar(2)您有:
a) 更具唯一性b)int索引大小小于varchar(2)

创建一个只包含所需部分的(计算)列,并在该列上建立索引?在guid的2个字符上建立索引效率非常低。这将是空间浪费。考虑一下真实guid上的ingex,如果您关心存储方面的考虑,那么您可以通过压缩表来节省一些空间。为什么要将guid存储为
varchar(36)
?正确的数据类型是
uniqueidentifier
-16字节,而不是38字节。从下面的注释来看,最好的方法是创建列“uniqueidentifier”,然后在此列上创建一个普通索引。创建一个(计算的)列,该列只包含所需的部分,并在该列上建立索引?对2个guid字符的索引效率非常低。这将是空间浪费。考虑一下真实guid上的ingex,如果您关心存储方面的考虑,那么您可以通过压缩表来节省一些空间。为什么要将guid存储为
varchar(36)
?正确的数据类型是
uniqueidentifier
-16字节,而不是38字节。从下面的注释来看,最好的方法是创建列“uniqueidentifier”,然后在此列上创建一个普通索引。您没有唯一性。GUID是128位整数。将它们转换为二进制,然后
int
将保留一端的32位,并截断其余的。另外,
int
varchar(2)
消耗的大小是相同的,都是4个字节(和
char(2)
2个字节)。这将更好地使用这4个字节,尽管
varchar(2)
只有256个不同的可能性,其中可能使用整个
int
范围,因此更具选择性。应用一个好的散列将是实现这个结果的一个更好的方法,而不是依赖GUID生成来提供一个好的分布。你是对的,这里没有唯一性。但是,它比使用左两个符号更独特。你没有唯一性。GUID是128位整数。将它们转换为二进制,然后
int
将保留一端的32位,并截断其余的。另外,
int
varchar(2)
消耗的大小是相同的,都是4个字节(和
char(2)
2个字节)。这将更好地使用这4个字节,尽管
varchar(2)
只有256个不同的可能性,其中可能使用整个
int
范围,因此更具选择性。应用一个好的散列将是实现这个结果的一个更好的方法,而不是依赖GUID生成来提供一个好的分布。你是对的,这里没有唯一性。但是,它比使用左2个符号更独特。