Azure-Sql-Database

將 nvarchar (4000) 更改為 nvarchar(500)

  • June 10, 2021

我有一個性能問題nvarchar(4000)。我想根據以下語句更改表格:

BEGIN  declare @length as int  
SELECT @length = MAX(LEN([SourceId])) 
from [dbo].[table] 
if   @length < 500  
begin  ALTER TABLE  [dbo].[table]   ALTER COLUMN [SourceId] NVARCHAR(500) NOT NULL;  end   
else   select ' column Length greater than 500' as tb  end

它會影響數據或索引嗎?我們在表中有超過 1000 萬行。

我首先要提醒您,將來最大長度為 500 的可能性太小。

也就是說,您的程式碼將起作用,儘管它會在表上獲取模式修改鎖,並且如果任何索引引用該列,則無法執行。

這是一篇關於模式修改鎖可能發生的一些問題的優秀文章:Michael J Swart的 Sch-M 鎖是邪惡的。

理想情況下,您在維護視窗中執行此操作,此時沒有事務處理表並且您有一些時間來處理它。

以下是一些範常式式碼,您可以使用它們來了解所涉及的時間:

/* Create Table */
DROP TABLE IF EXISTS dbo._Test 
CREATE TABLE dbo._Test 
(
ID INT IDENTITY (1,1) NOT NULL CONSTRAINT PK__TEST PRIMARY KEY CLUSTERED,
SourceID NVARCHAR(4000) NOT NULL
)

/* Optional Index */
CREATE NONCLUSTERED INDEX SourceID ON dbo._Test (SourceID) 

/* Load Table */ 
INSERT INTO dbo._Test (SourceID)

SELECT 
TOP 10000000
O1.Name
FROM 
sys.objects O1
CROSS JOIN sys.objects O2


/* Attempt ALTER */

ALTER TABLE dbo._Test 
ALTER COLUMN SourceID NVARCHAR(500)

/* 
   Fails Due To Index Depending On Column

Msg 5074, Level 16, State 1, Line 26
The index 'SourceID' is dependent on column 'SourceID'.
Msg 4922, Level 16, State 9, Line 26
ALTER TABLE ALTER COLUMN SourceID failed because one or more objects access this column.

*/

/* Drop the index */
DROP INDEX IF EXISTS SourceID ON dbo._Test

/* Try Again */

ALTER TABLE dbo._Test 
ALTER COLUMN SourceID NVARCHAR(500)

/*
Notice this takes a schema modification lock

   <Object name="_Test" schema_name="dbo">
     <Locks>
       <Lock resource_type="OBJECT" request_mode="Sch-M" request_status="GRANT" request_count="20" />
     </Locks>

Total time was ≈ 25 seconds on my test system, then may need to add back any indexes or constraints that were referencing the altered column.
*/

是的,縮短列長度將涉及重新處理表中的所有行以及可能的索引

https://michaeljswart.com/2013/04/altering-text-columns-only-a-metadata-change/

引用自:https://dba.stackexchange.com/questions/294014