SQL SERVER 索引

一、索引(Index)

在 SQL Server 中,索引(Index) 是一种数据库对象,它基于表或视图的一列或多列创建,其核心目的是极大地提高数据检索操作的速度,就像书籍的目录可以帮助你快速找到特定内容一样。

一、索引分类

1、聚集索引

  • 数据的实际存储顺序与我们做索引的顺序是一致的,这种索引我们将它成为聚集索引。表数据本身就被组织在聚集索引的 B+ 树的叶节点上。

2、非聚集索引

  • 数据的实际存储顺序与我们做的索引顺序不一致的时候,像这种快速查找数据的索引我们将它成为非聚集索引。

3、对比

特性聚集索引非聚集索引
数量限制每表仅有一个每表可有多个
数据存储叶子节点直接存储完整的行数据叶子节点存储索引列值 + 主键值
物理顺序数据按索引顺序物理排序索引逻辑连续,但对应的数据物理上无序
查询效率主键查询极快,​无需回表通过索引找到主键后,常需回表查询完整数据
范围查询极高效,可顺序读取连续数据块效率较低,需多次随机I/O回表
键值选择通常使用主键基于非主键的查询列

对于主键查询或覆盖索引的查询,数据库只需遍历一次聚集索引的B+树,在叶子节点就能拿到全部数据,过程非常直接。相比之下,非聚集索引的叶子节点只存有主键值查到所需数据的主键后,还需要拿着这些主键回到聚集索引里再查一次,这个过程称为“回表”,多了一次B+树的遍历,自然更慢

三、索引创建和使用方式

1、聚集索引

-- 语法
CREATE CLUSTERED INDEX index_name ON table_name (column_name [ASC | DESC]);
-- 案例
-- 对Users表的userid字段创建名称为IX_Users_UserID的聚集索引
CREATE CLUSTERED INDEX IX_Users_UserID on users (userid asc)

2、非聚集索引

-- 对Users表的Name字段创建名字为 IX_Users_Name的非聚集索引(可以省略NONCLUSTERED关键字,默认情况下CREATE INDEX 创建的是非聚集索引。
CREATE NONCLUSTERED INDEX  IX_Users_Name ON Users (Name) 

3、唯一索引

--创建唯一索引可以是聚集或者非聚集

--创建唯一聚集索引:对Users表的UserId字段创建名称为IX_Users_UserId的唯一聚集索引
CREATE UNIQUE CLUSTERED INDEX  IX_Users_UserId ON Users (UserId) 

--创建唯一非聚集索引:对Users表的Name字段创建名称为IX_Users_Name的唯一非聚集索引
CREATE UNIQUE NONCLUSTERED INDEX  IX_Users_Name ON Users (Name) 

--创建唯一非聚集索引(可以省略NONCLUSTERED关键字,默认情况下CREATE INDEX 创建的是非聚集索引。)
CREATE UNIQUE INDEX IX_Users_Name ON Users (Name) 

 案例:带条件的唯一索引

--对Users表,在DeleteTime字段为空的数据中,为Name字段添加唯一索引
CREATE UNIQUE INDEX  IX_Users_Name  ON Users (Name)  WHERE DeleteTime  is null

举例:Users表中有两列两行

NameDeleteTime
张三2022-02-10
李四NULL

此时想插入Name为李四的数据,无法插入,但是可以插入Name为张三的数据,因为张三这一行的DeleteTime列数据不为Null

案例1:带条件的唯一索引

--对Users表,在DeleteTime字段为空的数据中,为Name+Email字段添加唯一索引
CREATE UNIQUE INDEX  Index_Users_Name  ON Users (Name,Email)  
NameEmail     DeleteTime
张三abc@qq.comNULL  

User表中有三列一行 ,此时想插入一条Name为 张三,Email为 abc@qq.com的数据是不行的 ,但是可以插入一条Name为张三,Email为除abc@qq.com以外的任意值的数据 

或者可以插入一条Email为abc@qq.com,Name为除张三以外的任意值的数据

其实就是将Name和Email看成一个字段,两个字段共同组成一个唯一

案例2:带条件的唯一索引

-- 针对Users表,在DeleteTime字段为空的数据中,为Name+Email字段添加唯一索引,
-- 同时排除为DeleteTime不为空的数据添加唯一索引
-- 意思就是只为DeleteTime为空的数据添加唯一索引
CREATE UNIQUE INDEX  Index_Users_Name  ON Users (Name,Email)  WHERE DeleteTime  is null

4、覆盖索引

覆盖索引:特别适用于高频查询场景

-- 在 Users 表的 Status 列上创建一个非聚集索引,名称为:DEX IX_Users_Status,
-- 并且将 UserName、Email、CreatedDate 这三个列作为包含列(Included Columns) 
-- 存储在索引的叶子节点中,以便查询时无需回表(Key Lookup),
-- 直接从索引中获取所有所需数据。
CREATE NONCLUSTERED INDEX IX_Users_Status
ON Users (Status) 
INCLUDE (UserName, Email, CreatedDate);

-- ON Users (Status) 作用:指定索引建立在 Users 表的 Status 列上

-- INCLUDE (UserName, Email, CreatedDate) 作用如下:
-- 将 UserName、Email、CreatedDate 这三个列作为非键列(Included Columns) 添加到索引的叶子节点中。
-- 这些列不参与索引的排序和查找逻辑,但会物理存储在索引页中
-- 目的是让查询可以直接从索引中获取这些列的值,避免回表查询(Key Lookup)

覆盖索引的优势:

假设你经常执行以下查询:

SELECT UserName, Email, CreatedDate
FROM Users
WHERE Status = 'Active';

如果没有 INCLUDE,执行过程是:

  1. 使用索引找到 Status = 'Active' 的行(通过 Status 索引)。
  2. 然后回表(Key Lookup) 去主数据页查找 UserNameEmailCreatedDate 的值。
  3. 回表操作是I/O 密集型,性能较差。

而使用 INCLUDE

  1. 索引叶子节点已经包含了 UserNameEmailCreatedDate
  2. 查询可以直接从索引中获取所有数据,无需回表
  3. 这种索引称为 覆盖索引

5、筛选索引

优点:只索引满足条件的数据,节省空间,提升性能。

适用场景:大多数数据是“已归档”,只查询“活跃”用户。

-- 在 Users 表上创建一个非聚集筛选索引(其实就是非聚集索引加了一个where条件)
-- 它只包含 Status = 'Active' 的那些活跃用户,并对这些用户的 UserName 列建立索引
CREATE NONCLUSTERED INDEX IX_Users_ActiveOnly
ON Users (UserName)
WHERE Status = 'Active';

七、SQL语句的优化

--unique唯一索引,clustered聚集索引,nonclustered非聚集索引 。主键是唯一的,所以创建了一个主键的同时,也就这个字段创建了一个唯一的索引。SQL SERVER将主键默认定义为聚集索引,事实上,索引是否唯一与是否聚集是不相关的,聚集索引可以是唯一索引,也可以是非唯一索引; 唯一索引实际上就是要求指定的列中所有的数据必须不同

/*
 主键一唯一索引的区别:

         1 一个表的主键只能有一个,而唯一索引可以建多个。
         2 主键可以作为其它表的外键。
         3 主键不可为null,唯一索引可以为null。

聚集索引:将表内的数据按照一定的规则进行排列的目录。正因为如此,一个表中的聚焦索引只有一个。对此我们要注意“主键就是聚焦索引”这是极端错误的,是对聚焦索引的一种浪费。(虽然SQLServer默认主键就是聚焦索引)使用聚焦索引的最大好处就是按照查询要求,迅速缩小查询范围,避免进行全表扫描。其次让每个数目都不相同的字段作为聚焦索引也不符合“大数目不同情况下不应建立聚集索引的原则”。

*/

use sales
if(exists (select * from sys.indexes where name='IX_TEST_TName'))

drop index T_TESX.TX_TEST_TName  --如果IX_TEST_TName存在则删除该索引(注意删除索引的时候是 表名.索引名)
create nonclustered  index IX_TEST_TName  --创建一个非聚集索引索引
on T_Test(name) --为T_Test表的name字段创建索引
with fillfachor=30 --填充因子为30% 。可以省略with fillfachor=30这一句,省略即默认
go

创建唯一索引

CREATE UNIQUE INDEX IX_ApiClients_ClientId --针对ApiClients表的ClientId列做唯一索引
ON ApiClients (ClientId)

创建唯一索引和非唯一索引案例(非聚集)

/*
判断Users表是否存在,如果不存在则创建表,然后插入列说明,如果存在则插入列说明
*/
IF NOT EXISTS(SELECT TOP 1 * FROM sysObjects WHERE Id=object_id(N'Users') and xtype='U') 
BEGIN
	CREATE TABLE [dbo].[Users](
		[ID] INT NOT NULL,
		[UserName] [datetime] NOT NULL,
		[Email] [varchar](50) NOT NULL,
	)
	CREATE UNIQUE INDEX [ix_Users_UserName] ON Users --在UserName列上创建唯一索引,非聚集
   	(
		[UserName]
    )
	CREATE NONCLUSTERED  INDEX ix_Users_Email  ON Users --在Email列上创建不唯一索引,非聚集
	(
		[Email]
	)
	EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Users', @level2type=N'COLUMN',@level2name=N'ID'
	EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户名' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Users', @level2type=N'COLUMN',@level2name=N'UserName'
	EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'邮箱' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Users', @level2type=N'COLUMN',@level2name=N'Email'
END

ELSE

BEGIN
	EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Users', @level2type=N'COLUMN',@level2name=N'ID'
	EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户名' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Users', @level2type=N'COLUMN',@level2name=N'UserName'
	EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'邮箱' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Users', @level2type=N'COLUMN',@level2name=N'Email'
END

唯一索引与主键索引的比较 


唯一索引
 唯一索引不允许两行具有相同的索引值。
 如果现有数据中存在重复的键值,则大多数数据库都不允许将新创建的唯一索引与表一起保存。当新数据将使表中的键值重复时,数据库也拒绝接受此数据。例如,如果在 employee 表中的职员姓氏(lname) 列上创建了唯一索引,则所有职员不能同姓。

主键索引
 主键索引是唯一索引的特殊类型。
 数据库表通常有一列或列组合,其值用来唯一标识表中的每一行。该列称为表的主键。
 在数据库关系图中为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型。主键索引要求主键中的每个值是唯一的。当在查询中使用主键索引时,它还允许快速访问数据。

它们的一些比较:
(1)对于主健/unique constraint , oracle/sql server/mysql等都会自动建立唯一索引;
(2)主键不一定只包含一个字段,所以如果你在主键的其中一个字段建唯一索引还是必要的;
(3)主健可作外健,唯一索引不可;
(4)主健不可为空,唯一索引可;
(5)主健也可是多个字段的组合;
(6)主键与唯一索引不同的是:
a.有not null属性;
b.每个表只能有一个。

 

1、主键

主键ID,主键既是约束也是索引,同时也用于对象缓存的键值。

2、索引

       *组合或者引用关系的子表(数据量较大的时候),需要在关联主表的列上建立非聚集索引(如订单明细表中的产品ID字段、订单明细表中关联的订单ID字段)

       *索引键的大小不能超过900个字节,当列表的大小超过900个字节或者若干列的和超过900个字节时,数据库将报错。

       *表中如果建有大量索引将会影响INSERT、UPDATE和DELETE语句的性能,因为在表中的数据更改时,所有的索引都将必须进行适当的调整。需要避免对经常更新的表进行过多的索引,并且索引应保持较窄,就是说:列要尽可能的少。

       *为经常用于查询的谓词创建索引,如用于下拉参照快速查找的code、name等。在平台现有下拉参照的查询sql语句中的like条件语句要改成不带前置通配符。还有需要关注Order By和Group By谓词的索引设计,Order By和Group By的谓词是需要排序的,某些情况下为Order By和Group By的谓词建立索引,会避免查询时的排序动作。

       *对于内容基本重复的列,比如只有1和0,禁止建立索引,因为该索引选择性极差,在特定的情况下会误导优化器做出错误的选择,导致查询速度极大下降。

 

      *当一个索引有多个列构成时,应注意将选择性强的列放在前面。仅仅前后次序的不同,性能上就可能出现数量级的差异。

       *对小表进行索引可能不能产生优化效果,因为查询优化器在遍历用于搜索数据的索引时,花费的时间可能比执行简单的表扫描还长,设计索引时需要考虑表的大小。记录数不大于100的表不要建立索引。频繁操作的小数量表不建议建立索引(记录数不大于5000条)

1、 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:     

 select id from t where num is null

NULL对于大多数数据库都需要特殊处理,MySQL也不例外,它需要更多的代码,更多的检查和特殊的索引逻辑,有些开发人员完全没有意识到,创建表时NULL是默认值,但大多数时候应该使用NOT NULL,或者使用一个特殊的值,如0,-1作为默  认值。

不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列    就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。 任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。


此例可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: 

  select id from t where num=0

 2、 应尽量避免在 where 子句中使用!=或<>操作符
         否则将引擎放弃使用索引而进行全表扫描。
         MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。 
         可以在LIKE操作中使用索引的情形是指另一个操作数不是以通配符(%或者_)开头的情形。例如:      

 SELECT id FROM  t WHERE col LIKE 'Mich%'; --  这个查询将使用索引,
 SELECT id FROM  t WHERE col  LIKE '%ike';   --这个查询不会使用索引。

 3、 应尽量避免在 where 子句中使用 or 来连接条件,  否则将导致引擎放弃使用索引而进行全表扫描,如:      

​SELECT * FROM user WHERE userid=1 OR age=18;(假设userid有索引,age无索引)
--数据库优化器可能认为,与其先通过索引查找部分数据再回表扫描剩余部分,不如直接全表扫描效率更高
--优化建议:为无索引的字段(如age)添加索引,或使用UNION ALL重写查询

可以 使用UNION合并查询:

 select id from t where userid=10 union all select id from t where userid=20

 4、 如果在 where 子句中使用参数,也会导致全表扫描
 因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推 迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:      

select id from t where num=@num

可以改为强制查询使用索引: 

select id from t with(index(索引名)) where num=@num

 5、应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:   

select id from t where num/2=100 --查询条件是对 num 进行了运算:num / 2  导致全表扫描

-- 应改为:  

select id from t where num=100*2  --相当于select id from t where num=200 查询将变为索引查找

 6、应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:

select id from t where substring(name,1,3)='abc'   --name

select id from t where datediff(day,createdate,'2005-11-30')=0 --‘2005-11-30’ 

生成的id 应改为:

select id from t where name like 'abc%'

select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

7、 索引并不是越多越好。
索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。(一个表最多可以建249个索引)

8、用Where子句替换HAVING子句 。
避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销. (非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里

二、数据结构之二叉树数

通过链接可以添加数据,可以很直观的观察到使用二叉树结构来添加数据,索引是如何来检索数据的

以下是一个二叉树查询的示例:SQL SERVER的索引是采用B+树,而非二叉树。

二叉树的缺点

1、每个节点只有两个分支,树高约为 log2​(n),对于亿级数据,树高可能超过30层。

2、如果数据分布不均匀,可能退化为链表,导致查询效率急剧下降

三、数据结构之平衡二叉树

通过链接可以添加数据,可以很直观的观察到使用平衡二叉树结构来添加数据,索引是如何来检索数据的

1、平衡二叉树的核心概念

平衡二叉树又称为AVL树,是一种特殊的二叉搜索树(BST),其核心特性是自平衡。具体来说:

平衡因子 (Balance Factor): 对于树中的每一个节点,其左子树的高度减去右子树的高度的差值,称为该节点的平衡因子。

  • 平衡因子 = 左子树高度 - 右子树高度

平衡条件: 为了保证树的平衡,每个节点的平衡因子必须是 -1, 0, 或 1

  • -1:表示:右子树比左子树高1。
  • 0:表示:左右子树高度相等。
  • 1:表示:左子树比右子树高1。

一旦某个节点的平衡因子变为 2 或 -2,树就失去了平衡,需要通过旋转操作(左旋、右旋、左右旋、右左旋)来恢复平衡。

2、案例

四、数据结构之B+树

通过链接可以添加数据,可以很直观的观察到使用B+树结构来添加数据,索引是如何来检索数据的

五、SQL SERVER 的索引结构

微软官方文档

索引体系结构和设计指南:索引基础知识  聚集索引体系结构 与 非聚集索引体系结构

索引基础知识中描述:

索引是与表或视图关联的磁盘上或内存中结构,可以加快从表或视图中检索行的速度。 行存储索引包含从表或视图中一列或多列的值生成的键。 对于行存储索引,这些键存储在树结构(B+ 树)中,使数据库引擎能够快速高效地查找与键值关联的行。

聚集索引体系结构中描述:

行存储索引是按 B+ 树结构组织的,索引 B+ 树中的每一页称为一个索引节点。 B+ 树的顶端节点称为根节点。

聚集索引有单个分区。 当聚集索引有多个分区时,每个分区都有一个单独的 B+ 树结构,其中包含该特定分区的数据。 例如,如果聚集索引有四个分区,则每个分区有四个 B+ 树结构。

非聚集索引体系结构

基于磁盘的行存储非聚集索引与聚集索引具有相同的 B+ 树结构,但存在以下差异:

1、非聚集索引不一定包含表的所有列和行。

2、非聚集索引的叶级别是由索引页而不是由数据页组成。 非聚集索引的叶级别的索引页包含键列。 (可选)它们还可以包含表中其他列的子集(如包含的 ),以避免从基表检索它们。

非聚集索引行中的行定位符是指向行的指针,或者是行的聚集索引键,如下所示:

1、如果表有聚集索引或索引视图上有聚集索引,则行定位器是行的聚集索引键。

2、如果表是堆(意味着该表没有聚集索引),则行定位器是指向行的指针。 该指针由文件标识符 (ID)、页码和页上的行数生成。 整个指针称为行 ID (RID)。

五、索引的优缺点

一、索引的优点

1、提高查询性能

  • 这是索引最主要的优势。通过创建索引,特别是对 WHERE 子句、JOIN 条件和 ORDER BY 子句中使用的列建立索引,可以极大地加速数据的查找、排序和连接操作。

2、保证数据的唯一性

  • 唯一索引(Unique Index)可以确保索引列中的数据不重复,从而强制实施数据的实体完整性。例如,主键(Primary Key)和唯一约束(Unique Constraint)都会自动创建唯一索引

3、加速排序和分组

  • 如果 ORDER BY 或 GROUP BY 的列上有索引,SQL Server 可以利用索引的有序性来避免昂贵的 SORT 操作,直接按索引顺序读取数据

4、优化连接操作

  • 在多表连接(JOIN)时,如果连接条件(ON 子句)的列上有索引,SQL Server 可以更高效地找到匹配的行,从而提升连接性能。

5、支持覆盖查询

  • 当一个查询所需的所有列都包含在某个非聚集索引中时,SQL Server 可以直接从索引页获取数据,而无需访问数据页(堆或聚集索引页),这称为“覆盖查询”(Covering Query),能极大提升性能

二、索引的缺点

1、降低数据修改性能:当对表执行 INSERTUPDATE 或 DELETE 操作时,不仅需要修改表中的数据,还需要同步更新所有相关的索引。索引越多,维护索引的开销就越大,这会显著降低数据修改操作的性能。

2、增加维护成本:索引需要定期维护,例如重建重组索引以消除碎片,保持索引的高效性。这需要额外的系统资源和管理时间。

3、占用额外的存储空间:索引本身是物理存储在磁盘上的数据库对象,需要占用额外的磁盘空间。索引越多,占用的空间就越大。对于大型表,索引的大小甚至可能超过数据本身的大小

三、哪些列适合添加索引?

1. 经常用于 WHERE 子句的列

2. 经常作为 JOIN 条件的列(外键)

3. 经常出现在 ORDER BY 子句中的列

4. 经常出现在 GROUP BY 子句中的列

5. 需要保证唯一性的列

6. 选择性高的列(高基数列)

  • 原因:“选择性”是指列中不同值的数量与总行数的比例。选择性越高(即重复值越少),索引的效率就越高。例如,一个拥有百万用户的表,其 UserID(主键)的选择性极高,是理想的索引候选。而一个只有“男”、“女”两个值的 Gender 列,选择性很低,通常不适合单独建索引
  • 注意:对于低选择性的布尔值列(如 IsActive),如果数据分布极度不均(比如99%的用户都是激活状态),那么为 IsActive = 0(非激活)这样的条件创建索引可能仍然有效,这可以通过过滤索引(Filtered Index)来实现。

7. 复合索引(多列索引)中的列

  • 原因:当查询经常同时使用多个列时,创建一个包含这些列的复合索引通常比为每个列单独创建单列索引更高效。

四、哪些列不适合添加索引?

1、很少或从不在查询中使用的列:创建索引只会浪费空间和增加维护成本

2、更新非常频繁但很少用于查询的列:每次更新都会导致索引重建,开销巨大。

3、具有大量重复值的列(低选择性):如上面提到的 Gender,单独为其建立索引通常效果不佳

4、小表(例如少于几百行):对于小表,全表扫描的成本很低,索引带来的收益微乎其微,反而增加了开销

5、数据类型为 TEXTNTEXTIMAGE 或大型 VARCHAR(MAX) / NVARCHAR(MAX) 的列:这些大对象(LOB)列通常不适合直接索引(虽然 SQL Server 支持全文索引或包含列的方式处理)。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值