SqlServer 수직 분할 테이블(프로그램 변경 최소화)
수직 분표는 데이터베이스 디자인의 문제일 수 있기 때문에 상대적으로 보기 드물고 사용된다.만약에 데이터베이스에 있는 테이블의 일부 필드가 거의 변하지 않지만 자주 조회하고 일부 필드의 데이터가 빈번하게 변경된다면 이런 디자인은 같은 테이블에 넣는 것이 불합리하고 서로 영향이 너무 크다.변경된 테이블이 있을 때 열에 따라 테이블, 즉 수직으로 분할하는 것을 고려할 수 있다.
수직으로 시계를 나누는 사례가 비교적 적기 때문에 최근에 이런 시계가 존재하기 때문에 개인적으로 부추겼다.
소스 테이블 설계 구조:
--
CREATE TABLE [dbo].[DemoTab](
[Guid] [uniqueidentifier] NOT NULL,
[UserName] [nvarchar](30) NOT NULL,
[Password] [nvarchar](30) NOT NULL,
[UserAccount] [varchar](30) NOT NULL,
[Amount] [numeric](18, 4) NULL,
CONSTRAINT [PK_DemoTab] PRIMARY KEY CLUSTERED ([Guid])
)
GO
ALTER TABLE [dbo].[DemoTab]
ADD CONSTRAINT [DF_DemoTab_Guid] DEFAULT (newsequentialid()) FOR [Guid]
GO
-- ( )
CREATE VIEW [dbo].[VDemoTab]
AS
SELECT [Guid],[UserName],[Password],[UserAccount],[Amount]
FROM [dbo].[DemoTab]
GO
주: 분할 후 각 표의 메인 키는 모두 같고 분할 후의 표는 규범화되었다.지금 시계 두 장으로 뜯어주세요.
시계를 기표로 선택하는 것을 주의하십시오. 다른 시계는 모두 이 시계와 키를 가지고 있습니다.
-- 【1】, " ", " "
CREATE TABLE [dbo].[DemoTab001](
[Guid] [uniqueidentifier] NOT NULL,
[UserName] [nvarchar](30) NOT NULL,
[Password] [nvarchar](30) NOT NULL,
CONSTRAINT [PK_DemoTab001] PRIMARY KEY CLUSTERED ([Guid])
)
GO
-- ,
--ALTER TABLE [dbo].[DemoTab001]
--ADD CONSTRAINT [DF_DemoTab001_Guid] DEFAULT (newsequentialid()) FOR [Guid]
--GO
-- 【2】," "
CREATE TABLE [dbo].[DemoTab002](
[Guid] [uniqueidentifier] NOT NULL,
[UserAccount] [varchar](30) NOT NULL,
[Amount] [numeric](18, 4) NULL,
CONSTRAINT [PK_DemoTab002] PRIMARY KEY CLUSTERED ([Guid])
)
GO
-- ,
--ALTER TABLE [dbo].[DemoTab002]
--ADD CONSTRAINT [DF_DemoTab002_Guid] DEFAULT (newsequentialid()) FOR [Guid]
--GO
-- ( , ON UPDATE CASCADE)
ALTER TABLE [dbo].[DemoTab002]
ADD CONSTRAINT [FK_DemoTab002_DemoTab001_Guid] FOREIGN KEY ([Guid])
REFERENCES [DemoTab001]([Guid]) ON UPDATE CASCADE ON DELETE CASCADE
GO
이전에 단일 테이블이나 보기에 대한 조작이었다면, 분할 후 논리적 층의 변경이 많을 수 있으며, 변경을 최소화하기 위해 연합 보기로 조작할 수 있다.어떻게 연결표를 개인 상황에 따라 정합니까?
-- (INNER JOIN )
ALTER VIEW [dbo].[VDemoTab]
AS
SELECT T1.[Guid],T1.[UserName],T1.[Password],T2.[UserAccount],T2.[Amount]
FROM [dbo].[DemoTab001] T1 LEFT JOIN [dbo].[DemoTab002] T2 ON T1.[Guid]=T2.[Guid]
GO
이 때 문제가 왔습니다. 시계에 대해 DML 조작을 해야 합니다. insert, update, delete는 어떻게 해결합니까?메인 키가 여러 테이블에 분산되어 있고 같은 것을 요구하기 때문이다!이때 트리거를 고려해서만 일치성을 확보할 수 있으며, 트리거는 보기에 정의되어 있으며, INSTEAD OF 유형의 트리거를 사용한다.
insert 트리거:
보기 [VDemoTab]의 [Guid]는 시계 삽입 시간값입니다. 트리거 삽입 중 가상 시계 [inserted]의 [Guid]가 유일하기 때문에 트리거에서 이 [Guid]를 여러 개의 시계에 동시에 삽입할 수 있습니다. 여러 개의 시계의 [Guid]가 동일하다는 것을 보장합니다!
-- insert
CREATE TRIGGER [dbo].[tgr_VDemoTab_insert]
ON [dbo].[VDemoTab]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO [dbo].[DemoTab001]([Guid],[UserName],[Password])
SELECT [Guid],[UserName],[Password] FROM inserted;
INSERT INTO [dbo].[DemoTab002]([Guid],[UserAccount],[Amount])
SELECT [Guid],[UserAccount],[Amount] FROM inserted;
END
GO
업데이트 트리거:마찬가지로 업데이트할 때 가상 테이블 deleted와 inserted가 관련되고 업데이트는 보기 [VDemoTab]에 대한 업데이트이기 때문에 가상 테이블 inserted는 모든 필드를 포함하기 때문에 트리거가 각각 여러 개의 테이블을 업데이트해야 한다.
-- update
CREATE TRIGGER [dbo].[tgr_VDemoTab_update]
ON [dbo].[VDemoTab]
INSTEAD OF UPDATE
AS
BEGIN
UPDATE T1 SET
T1.[UserName] = T2.[UserName],
T1.[Password] = T2.[Password]
FROM [dbo].[DemoTab001] AS T1, inserted AS T2 WHERE T1.[Guid] = T2.[Guid]
UPDATE T1 SET
T1.[UserAccount] = T2.[UserAccount],
T1.[Amount] = T2.[Amount]
FROM [dbo].[DemoTab002] AS T1, inserted AS T2 WHERE T1.[Guid] = T2.[Guid]
END
GO
delete 트리거:뷰 [VDemoTab] 레코드를 삭제하고 여러 테이블과 관련하여 삭제할 수 없으므로 마스터 테이블의 레코드만 삭제하면 다른 테이블은 종속 삭제됩니다.
-- delete
CREATE TRIGGER [dbo].[tgr_VDemoTab_delete]
ON [dbo].[VDemoTab]
INSTEAD OF DELETE
AS
BEGIN
DELETE FROM [dbo].[DemoTab001]
WHERE [Guid] IN (SELECT [Guid] FROM deleted)
END
GO
설계는 기본적으로 완성되었고, 지금 테스트를 진행한다.
INSERT INTO [dbo].[VDemoTab]([Guid],[UserName],[Password],[UserAccount],[Amount])
SELECT NEWID(),'user01','pw01','account01',100
UNION ALL
SELECT NEWID(),'user02','pw02','account02',99
UNION ALL
SELECT NEWID(),'user03','pw03','account03',0
GO
UPDATE [VDemoTab] SET [Password]='pw',[Amount]='10'
WHERE [Amount] >=0 AND [Amount]<100 AND [UserName] LIKE '%3'
GO
DELETE FROM [VDemoTab] WHERE [UserName] = 'user03'
GO
SELECT * FROM [dbo].[DemoTab001]
SELECT * FROM [dbo].[DemoTab002]
SELECT * FROM [dbo].[VDemoTab]
기본 조작은 모두 정상이다!수직 분표 완성!성능은 어떻습니까?
Guid가 주 키로 사용되기 때문에 NEWSEQUENTIALID() 대신 NEWID() 를 사용합니다. 레코드가 추가될 때 인덱스를 모아 많은 데이터를 다시 정렬할 수 있습니다.
표를 나누면 한 개의 데이터 페이지에 저장할 수 있는 데이터가 더 많지만 여러 개의 표로 나누면 데이터 페이지도 많아지고 Guid는 모든 표에 존재하기 때문에 데이터를 조회할 때 IO가 더 많아진다.
업데이트 데이터에 대해 트리거에서 두 개의 테이블이 동시에 업데이트되며, 그 중 한 개의 테이블을 업데이트해도 다른 테이블은 영향을 미친다.만약 시계를 나눈 후에 동시에 업데이트하지 않는다면 트리거에서if(update(col))를 사용하여 업데이트가 그 열이라고 판단하면 해당하는 기본 시계를 업데이트하면 되고 다른 시계는 업데이트하지 않습니다.
가장 좋은 상황은 분할된 표는 모두'독립적'이다. 연합 보기를 사용하지 않고 조회와 변경이 독립적이기 때문에 논리층을 변경해야 한다.
이 SqlServer 수직분표(프로그램 변경 감소)에 관한 글은 여기 소개되어 있습니다. 더 많은 SqlServer 수직분표 내용은 저희 이전의 글을 검색하거나 아래의 관련 글을 계속 훑어보십시오. 앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
SQL 프로 세 스 잠 금 해결 방법sp_who active sp_who2 ======================================== 1:sp_who sp_who2 2: Select * from sysprocesses where bloc...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.