列的一部分上的SQL索引

时间:2017-09-18 06:23:37

标签: sql-server indexing

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

但是最近我被要求查询此表以查找特定的GUID。

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

有没有办法可以在列上添加索引,但只能在前2个字符上添加?

这应该足以将数据集减少到足够小的数量,然后去做物理读取?导致速度和存储空间混合。

简而言之,如果我有一个名为varchar(36)的{​​{1}}列,我是否可以仅在该列的前两个字符上添加索引?

ID

2 个答案:

答案 0 :(得分:2)

  

如果我有一个名为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

要在计算列上创建索引,它已满足一些解释为here的属性,您可以检查列是否满足这些属性

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 property is not satisfied,您可能需要保留该列,然后可能占用空间

注意:
在大型列上创建计算索引可能需要大量内存来排序(使用:在tempdb选项中排序)并且您可能会耗尽内存。我试图在260亿行数据(历史数据)上创建计算索引并且失败< / p>

您的新计算列不是唯一的

答案 1 :(得分:0)

您可以索引[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)