유지 관리 스크립트를 더 잘 이해하기 위해 SQL Server 2017 테스트 데이터베이스에서 의도적으로 잘못된 인덱스 조건을 만들고 싶습니다. SQL Server 인덱스 및 통계 유지 관리
인덱스 무결성을 손상 시키거나 인덱스 조각화를 증가시키는 빠르고 자동적 인 방법이 있습니까? 이것을 달성하기 위해 내가 볼 수있는 유용한 자료를 알고 있습니까?
DBCC SHRINKDATABASE ([yourNONProdDB])
유지 관리 스크립트를 더 잘 이해하기 위해 SQL Server 2017 테스트 데이터베이스에서 의도적으로 잘못된 인덱스 조건을 만들고 싶습니다. SQL Server 인덱스 및 통계 유지 관리
인덱스 무결성을 손상 시키거나 인덱스 조각화를 증가시키는 빠르고 자동적 인 방법이 있습니까? 이것을 달성하기 위해 내가 볼 수있는 유용한 자료를 알고 있습니까?
DBCC SHRINKDATABASE ([yourNONProdDB])
답변:
내가 상상할 수있는 한 가지 빠른 방법 UNIQUEIDENTIFIER
은 기본 키로 테이블을 만들고 많은 임의의 값을 삽입하는 것입니다. 이 스크립트를 사용하여 달성 할 수 있습니다.
CREATE TABLE dbo.Tests (Id UNIQUEIDENTIFIER PRIMARY KEY);
GO
INSERT INTO dbo.Tests (Id)
WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
SELECT NEWID()
FROM x AS x1, x AS x2, x AS x3, x AS x4, x AS x5, x AS x6;
이것은 백만 개의 행을 생성합니다.
이것이 NEWID()
순서를 보장하지는 않는다는 것을 알기 때문에 SQL Server는 테이블의 임의의 지점에 삽입해야합니다. 그러면 기본 키가 조각화됩니다.
INSERT dbo.Tests (Id) SELECT NEWID(); GO 1000000;
. 다른 질문에 대해 함께 정리 한 예제는 pastebin.com/SVLtiRnP 를 참조하십시오 . 가변 길이 행을 사용하고 무작위로 업데이트하면 조각화가 더 효율적일 수 있습니까?
몇 가지 "추악한"색인을 만들고 싶었으므로 다음을 수행했습니다. 잘 작동했습니다
-- Create databases to test index job, each database is about 800MB with 100,000 GUID primary keys, in each of two tables
-- Create 6 database to test index job for DatabasesInParallel Database design based on example https://dba.stackexchange.com/q/9821/21924
--Drop last test
USE [master]
exec asp_kill_user_connections [IndexTest_1]
exec asp_kill_user_connections [IndexTest_2]
exec asp_kill_user_connections [IndexTest_3]
exec asp_kill_user_connections [IndexTest_4]
exec asp_kill_user_connections [IndexTest_5]
exec asp_kill_user_connections [IndexTest_6]
GO
DROP DATABASE [IndexTest_1]
GO
DROP DATABASE [IndexTest_2]
GO
DROP DATABASE [IndexTest_3]
GO
DROP DATABASE [IndexTest_4]
GO
DROP DATABASE [IndexTest_5]
GO
DROP DATABASE [IndexTest_6]
GO
-- create [IndexTest_1]
USE [master];
GO
CREATE DATABASE [IndexTest_1];
GO
USE IndexTest_1
SET NOCOUNT ON
CREATE TABLE TestGuidA (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
CREATE TABLE TestGuidB (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000
WHILE (@BatchCounter <= 20)
BEGIN
BEGIN TRAN
DECLARE @LocalCounter INT = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidA (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @LocalCounter = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidB (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @BatchCounter +=1
COMMIT
END
-----------------------------------------------
-- create [IndexTest_2]
USE [master];
GO
CREATE DATABASE [IndexTest_2];
GO
USE IndexTest_2
SET NOCOUNT ON
CREATE TABLE TestGuidA (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
CREATE TABLE TestGuidB (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000
WHILE (@BatchCounter <= 20)
BEGIN
BEGIN TRAN
DECLARE @LocalCounter INT = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidA (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @LocalCounter = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidB (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @BatchCounter +=1
COMMIT
END
------------------------------------
-- create [IndexTest_3]
USE [master];
GO
CREATE DATABASE [IndexTest_3];
GO
USE IndexTest_3
SET NOCOUNT ON
CREATE TABLE TestGuidA (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
CREATE TABLE TestGuidB (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000
WHILE (@BatchCounter <= 20)
BEGIN
BEGIN TRAN
DECLARE @LocalCounter INT = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidA (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @LocalCounter = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidB (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @BatchCounter +=1
COMMIT
END
----------------------------------------
-- create [IndexTest_4]
USE [master];
GO
CREATE DATABASE [IndexTest_4];
GO
USE IndexTest_4
SET NOCOUNT ON
CREATE TABLE TestGuidA (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
CREATE TABLE TestGuidB (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000
WHILE (@BatchCounter <= 20)
BEGIN
BEGIN TRAN
DECLARE @LocalCounter INT = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidA (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @LocalCounter = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidB (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @BatchCounter +=1
COMMIT
END
------------------------------------------------
-- create [IndexTest_5]
USE [master];
GO
CREATE DATABASE [IndexTest_5];
GO
USE IndexTest_5
SET NOCOUNT ON
CREATE TABLE TestGuidA (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
CREATE TABLE TestGuidB (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000
WHILE (@BatchCounter <= 20)
BEGIN
BEGIN TRAN
DECLARE @LocalCounter INT = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidA (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @LocalCounter = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidB (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @BatchCounter +=1
COMMIT
END
--------------------------------------------
-- create [IndexTest_6]
USE [master];
GO
CREATE DATABASE [IndexTest_6];
GO
USE IndexTest_6
SET NOCOUNT ON
CREATE TABLE TestGuidA (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
CREATE TABLE TestGuidB (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))
DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000
WHILE (@BatchCounter <= 20)
BEGIN
BEGIN TRAN
DECLARE @LocalCounter INT = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidA (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @LocalCounter = 0
WHILE (@LocalCounter <= @NumRows)
BEGIN
INSERT TestGuidB (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
SET @LocalCounter +=1
END
SET @BatchCounter +=1
COMMIT
END
-------------------------------
use master
DBCC FREEPROCCACHE -- Clear plan cache for next text.
일반적으로 인덱스 조각화 는 테이블에 Update
있거나 Insert
작업이 수행 될 때 발생합니다.
당신이 문제 (인덱스 조각)을 생산하고 신속하게 원하는 경우,을 만들 Index
적은 비용으로 테스트 테이블에 fill factor
무거운 할 Update
또는 Insert
해당 테이블에 작업을. 이 스크립트로 작업 할 수 있습니다.
CRYPT_GEN_RANDOM
이 답변에서했던 것처럼 인덱스 최적화 스크립트의 필터 스키마를 사용할 수도 있습니다 .
다음과 같이 조각화하기 위해 인덱스가있는 숫자 열에 데이터를 삽입 할 수 있습니다.
-- Fill with random integers to create fragmentation
INSERT INTO [ProdTable] (c1, c2) VALUES (CRYPT_GEN_RANDOM(8000), 'filler');
GO 12800
필요한 경우 데이터를 업데이트하거나 숫자 대신 문자열로 변환 할 수도 있습니다.