SQL Server 创建索引的限制

在SQL Server中创建索引时,遇到900字节的键长度限制。当包含多个或大尺寸列时,需确保不超过最大索引键大小。警告提示可能在插入/更新操作时因键值超过900字节而失败。可以考虑使用非聚集索引的INCLUDE子句来包含非键列,以避免键列大小限制。

今天准备在SQL Server2005的一个表的字段上间索引,结果创建失败。检查一下表结构,原来该字段是NVarchar(Max), 不能建索引。 

 

后来将该字段改成nvarchar(4000),重新执行创建语句,出现如下提示:

Warning! The maximum key length is 900 bytes. The index 'IX_PROJECT_LABEL' has maximum length of 8000 bytes. For some combination of large values, the insert/update operation will fail.

 

查询MSDN,

解释如下:

 

Maximum Size of Index Keys

When you design an index that contains many key columns, or large-size columns, calculate the size of the index key to make sure that you do not exceed the maximum index key size. SQL Server retains the 900-byte limit for the maximum total size of all index key columns. This excludes nonkey columns that are included in the definition of nonclustered indexes.

To calculate the size of an index key, follow these steps.

  1. Display the properties of the table columns on which the index will be based. You can do this by using the sys.columns catalog view.
  2. Sum the length of each column that will be defined in the index key.
    For example, the following statement aggregates the max_length column of the sys.columns catalog view for the specified columns in the Person.Address table.
    USE AdventureWorks;
    GO
    SELECT SUM(max_length)AS TotalIndexKeySize
    FROM sys.columns
    WHERE name IN (N'AddressLine1', N'AddressLine2', N'City', N'StateProvinceID', N'PostalCode')
    AND object_id = OBJECT_ID(N'Person.Address');
    ms191241.note(en-us,SQL.100).gifNote:
    If a table column is a Unicode data type such as nchar or nvarchar, the column length displayed is the storage length of the column. This is two times the number of characters specified in the CREATE TABLE statement. In the previous example, City is defined as an nvarchar(30) data type; therefore, the storage length of the column is 60.

  3. If the total length is less than 900 bytes, the columns can participate as index key columns. If the total length exceeds 900 bytes, review the following information for options and additional considerations.
    The CREATE INDEX statement uses the following algorithms to calculate the index key size:
    • If the size of all fixed key columns plus the maximum size of all variable key columns specified in the CREATE INDEX statement is less than 900 bytes, the CREATE INDEX statement finishes successfully without warnings or errors.
    • If the size of all fixed key columns plus the maximum size of all variable key columns exceeds 900, but the size of all fixed key columns plus the minimum size of the variable key columns is less than 900, the CREATE INDEX statement succeeds with a warning that a subsequent INSERT or UPDATE statement may fail if it specifies values that generates a key value larger than 900 bytes. The CREATE INDEX statement fails when existing data rows in the table have values that generate a key larger than 900 bytes. A subsequent INSERT or UPDATE statement that specifies data values that generates a key value longer than 900 bytes fails.
    • If the size of all fixed key columns plus the minimum size of all variable columns specified in the CREATE INDEX statement exceeds 900 bytes, the CREATE INDEX statement fails.
    The following table summarizes the results of creating indexes that meet or exceed the maximum index key size restrictions.

Minimum size of variable-length column(s) + Size of the fixed-data column(s) Maximum size of variable-length column(s) + Size of the fixed-data column(s) MAX of the SUM of the index key column lengths for existing rows* Index is created Message type INSERT or UPDATE run-time error caused by oversized index key value

> 900 bytes

Not relevant

Not relevant

No

Error

No index present to generate error.

<= 900 bytes

<= 900 bytes

Not relevant

Yes

None

No.

<= 900 bytes

> 900 bytes

<= 900 bytes

Yes

Warning

Only if the sum of current lengths of all index columns is greater than 900 bytes.

<= 900 bytes

> 900 bytes

> 900 bytes

No

Error

No index present to generate error.

* None of the rows in the table at time the CREATE INDEX statement is executed can have index key values whose total lengths exceed 900 bytes.

You can include nonkey columns in a nonclustered index to avoid the current index size limitations of a maximum of 16 key columns and a maximum index key size of 900 bytes. The SQL Server Database Engine does not consider nonkey columns when calculating the number of index key columns or the total size of the index key columns. In a nonclustered index with included columns, the total size of the index key columns is restricted to 900 bytes. The total size of all nonkey columns is limited only by the size of the columns specified in the INCLUDE clause; for example, varchar(max) columns are limited to 2 GB. The columns in the INCLUDE clause can be of all data types, except text, ntext, and image.

<think>我们正在回答用户关于SQL Server创建索引的方法和示例的问题。 根据用户提供的引用资料,我们可以总结如下: 引用[1]和[2]介绍了SQL Server索引的基本概念和类型,包括聚集索引和非聚集索引。 引用[3]给出了一个简单的创建非聚集索引的示例。 因此,我们将按照以下结构组织回答: 1. 索引的基本概念和类型(聚集索引、非聚集索引等) 2. 创建索引的基本语法 3. 创建索引的示例(包括聚集索引、非聚集索引、复合索引等) 4. 注意事项 同时,我们还需要注意,用户之前的问题是关于表达式索引的,但根据当前提供的引用,SQL Server中并没有直接提到表达式索引(函数索引),不过我们可以提一下SQL Server中实现类似功能的方法(例如计算列上的建索引)。 但是,由于用户当前的问题明确要求SQL Server创建索引的方法和示例,我们应集中在基本索引创建上。 另外,根据引用[1]和[2]: - 聚集索引:一个表只能有一个,通常在主键上创建,但也可以在其他列上创建,它会改变数据的物理存储顺序。 - 非聚集索引:一个表可以有多个,它创建一个单独的索引结构,包含指向数据行的指针。 我们按照以下步骤进行: 步骤1:介绍基本语法 步骤2:给出创建不同类型索引的示例 步骤3:注意事项 最后,根据要求生成相关问题。 注意:用户提供的引用中没有直接提到表达式索引,所以我们可以简要提一下SQL Server中通过计算列索引来实现表达式索引的功能(虽然这不是用户直接问的,但可以作为一个补充点,因为用户之前的问题涉及表达式索引)。 由于引用中没有提供计算列索引的示例,我们可以简单解释: 在SQL Server中,可以通过先创建一个计算列,然后在该计算列上创建索引,从而实现对表达式的索引。例如: 假设我们有一个表`employees`,我们想对`last_name`的小写建立索引: ```sql -- 添加一个计算列 ALTER TABLE employees ADD last_name_lower AS LOWER(last_name); -- 在计算列上创建索引 CREATE INDEX idx_employees_lastname_lower ON employees(last_name_lower); ``` 但要注意,用户的问题并不要求这个,所以我们把它作为补充内容放在注意事项或示例部分。 现在,我们开始组织回答。 </think> ### SQL Server 索引创建指南 在 SQL Server 中,索引是优化查询性能的核心工具。以下是索引创建的方法和示例: #### 一、索引类型与语法 1. **基本语法** ```sql CREATE [UNIQUE] [CLUSTERED|NONCLUSTERED] INDEX index_name ON table_name (column1 [ASC|DESC], ...) [INCLUDE (columnX, ...)] [WHERE filter_condition]; -- SQL Server 2016+ 支持筛选索引 ``` 2. **索引类型对比** | 类型 | 数量限制 | 存储方式 | 适用场景 | |---|---|---|---| | **聚集索引** | 每表1个 | 数据行按索引顺序存储 | 主键、范围查询 | | **非聚集索引** | 每表999个 | 独立结构指向数据行 | 频繁查询的非主键列 | | **唯一索引** | 无限制 | 强制列值唯一性 | 防止重复值的列 | | **复合索引** | 最多16列 | 多列组合 | 多条件查询 | | **筛选索引** | 无限制 | 带WHERE条件的子集 | 稀疏数据优化[^1] | #### 二、创建索引示例 1. **基本索引创建** ```sql -- 在employees表的age列创建非聚集索引 CREATE INDEX idx_employees_age ON employees (age); ``` 2. **聚集索引(通常在主键上自动创建)** ```sql -- 创建主键时自动生成聚集索引 ALTER TABLE orders ADD CONSTRAINT PK_OrderID PRIMARY KEY CLUSTERED (order_id); ``` 3. **复合索引** ```sql -- 在sales表的region和sale_date列创建复合索引 CREATE NONCLUSTERED INDEX idx_sales_region_date ON sales (region, sale_date DESC); ``` 4. **包含列索引(Covering Index)** ```sql -- 索引包含额外列避免键查找 CREATE INDEX idx_cust_name_email ON customers (last_name) INCLUDE (first_name, email); ``` 5. **筛选索引SQL Server 2016+)** ```sql -- 仅索引活跃用户 CREATE INDEX idx_users_active ON users (last_login) WHERE is_active = 1; ``` #### 三、最佳实践与注意事项 1. **列选择原则** - 优先选择高选择性列(唯一值比例高) - WHERE/JOIN/ORDER BY/GROUP BY子句中的列 - 避免在频繁更新的列上建过多索引 2. **性能影响** - **写入开销**:每次INSERT/UPDATE/DELETE需更新索引,降低写入速度 - **空间占用**:非聚集索引额外占用约表大小的10-15%[^2] - **维护成本**:定期重建碎片化索引(`ALTER INDEX ... REBUILD`) 3. **表达式索引实现** SQL Server 通过计算列模拟表达式索引: ```sql -- 1. 添加计算列 ALTER TABLE products ADD price_with_tax AS (price * 1.1); -- 2. 在计算列建索引 CREATE INDEX idx_products_taxed_price ON products(price_with_tax); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值