MSSql 저장 프로 세 스 효율 적 인 응용

저장 프로시저 보안
최근 에 대형 채 팅 방 프로젝트 를 하고 있 습 니 다. 저 는 데이터베이스 와 소프트웨어 배경 을 맡 고 있 습 니 다.안전성 을 고려 하여 우리 개발 팀 은 모든 SQL 문 구 를 저장 프로 세 스 로 밀봉 한 다음 에 원 격 으로 sql 계 정 을 방문 하고 이 저장 프로 세 스 의 실행 권한 을 이 sql 계 정 에 부여 하기 로 결정 했다.저장 프로 세 스 를 작성 할 때 우리 의 저장 프로 세 스 이름 은 비교적 의미 있 고 규칙 적 입 니 다. 안전 을 향상 시 키 기 위해 우리 팀 은 저장 프로 세 스 의 이름 을 다시 암호 화 했 습 니 다.
저장 프로시저 성능
대형 채 팅 방 프로그램 이 데이터 베 이 스 를 읽 는 것 은 매우 평범 하 다. 예 를 들 어 모든 사용자 가 하나의 채 팅 방 에 들 어가 면 그 는 먼저 데이터 베이스 에서 이 채 팅 방 에 있 는 게이머 정 보 를 읽 어야 한다. 그러나 모든 게이머 정보 필드 는 100 개의 필드 에 가 깝 지 않 고 각 확장 표 에 분포 한다.어떤 시간 에 한 확장 표 의 여러 데이터 가 메 인 표 의 한 데이터 와 연결 되 므 로 지부 조회 가 필요 합 니 다.이러한 조 회 는 프로그램 에서 비교적 잘 이 루어 지지 만 그의 단점 도 있다. 예 를 들 어 방 에 1 만 명의 사용자 가 있다 면 우 리 는 1 만 명의 사용자 의 기본 정 보 를 읽 으 려 면 1 만 번 의 데이터 베 이 스 를 조회 해 야 한다.만약 우리 가 이 만 명의 사용자 의 상세 한 정 보 를 표시 해 야 한다 면, 몇 만 번 의 데이터 베 이 스 를 조회 해 야 한다. 이렇게 하면 분명히 안 된다.
10000 개의 데 이 터 를 한꺼번에 읽 는 것 은 한 번 에 10 개의 데 이 터 를 읽 는 것 보다 1000 번 연속 읽 는 효율 이 훨씬 빠르다.
우리 자신의 방법 은 논리 적 처 리 를 저장 과정 에 기록 하 는 것 이다. 서버 는 이러한 저장 과정 만 호출 하면 목적 을 달성 할 수 있다.
create proc proc_name
(
@userIds varchar(max)  --이 방 의 모든 사용자 id 는 쉼표 로 구 분 됩 니 다.
)
as
begin
/ / 논리 처리, 각종 순환 판단 커서
select * from #tableName
end
EXEC proc_name '1,2,3,4,5,6,7'
이렇게 하면 데이터 베 이 스 를 한 번 만 방문 하면 모든 데 이 터 를 얻 을 수 있다.
이런 코드 를 공유 해 보도 록 하 겠 습 니 다.
 create proc [dbo].[Proc_#CombinationService]  
     (  
        @SplitString nvarchar(100),  
         @FieldSeparator nvarchar(10)='|',  
         @GroupSeparator nvarchar(10)='&',  
         @ReturnData nvarchar(2000) output  
     )  
     AS  
     BEGIN  
         DECLARE @CurrentIndex int;  
         DECLARE @NextIndex int;  
         DECLARE @ReturnText nvarchar(100);  
         DECLARE @Return nvarchar(1000)=''  
         DECLARE @ServiceNumber varchar(100);  
         DECLARE @ServiceName varchar(100);  
         DECLARE @ServiceLevel varchar(100);  
         DECLARE @IconNumber varchar(100);  
         DECLARE @Explain varchar(150);  
         SELECT @CurrentIndex=1;  
         WHILE(@CurrentIndex<=len(@SplitString))  
             BEGIN  
                 SELECT 
                 @NextIndex=charindex(@FieldSeparator,@SplitString,@CurrentIndex);
                 IF(@NextIndex=0 OR @NextIndex IS NULL)  
                     SELECT @NextIndex=len(@SplitString)+1;  
                     SELECT @ReturnText=substring(@SplitString,@CurrentIndex,@NextIndex-@CurrentIndex);
                     select @ServiceNumber=ServiceNumber,@ServiceName=ServiceName,
			@ServiceLevel=ServiceLevel,  
                   	@IconNumber=IconNumber,@Explain=Explain  
                     from UserServiceInfo where ServiceNumber=@ReturnText  
                     set @Return=@ServiceNumber+@FieldSeparator+@ServiceName+
			@FieldSeparator+@ServiceLevel
			+@FieldSeparator+@IconNumber+@FieldSeparator+@Explain+@GroupSeparator+@Return  
                     SELECT @CurrentIndex=@NextIndex+1;  
                 END  
           set @ReturnData=@Return  
        RETURN;  
     END  
create PROCEDURE [dbo].[Proc_#UsersInfo_GetDataInfo]  
     (  
         @SplitString nvarchar(100),  
        @FieldSeparator nvarchar(10)='|'  
     )  
     AS  
     begin  
    CREATE TABLE #t(UserNumber INT PRIMARY KEY,NickName varchar(20),
	LiangNumber varchar(20),GroupNumber int,
	Avatar varchar(100),ServicesNumber varchar(100),ReturnData nvarchar(2000))  
        DECLARE @CurrentIndex int;  
        DECLARE @NextIndex int;  
        DECLARE @ReturnText nvarchar(100);  
        DECLARE @ReturnData nvarchar(2000);  
        DECLARE @UserNumber INT;  
        DECLARE @NickName varchar(20);  
        DECLARE @LiangNumber varchar(20);  
        DECLARE @GroupNumber int;  
        DECLARE @Avatar varchar(100);  
        DECLARE @ServicesNumber nvarchar(100);  
        SELECT @CurrentIndex=1  
        WHILE(@CurrentIndex<=len(@SplitString))  
            BEGIN  
         SELECT @NextIndex=charindex(@FieldSeparator,@SplitString,@CurrentIndex);  
                IF(@NextIndex=0 OR @NextIndex IS NULL)  
                    SELECT @NextIndex=len(@SplitString)+1;  
                    SELECT @ReturnText=substring(@SplitString,@CurrentIndex,@NextIndex-@CurrentIndex);  
                    select  @UserNumber=UserNumber,@NickName=NickName,
			@LiangNumber=LiangNumber,@GroupNumber=GroupNumber,
			@Avatar=Avatar,@ServicesNumber=ServicesNumber from View_ClientUserList  
                    where UserNumber=@ReturnText  
                    exec [Proc_#CombinationService] @ServicesNumber,'|','#',
			@ReturnData output  
                    insert into #t(UserNumber,NickName,LiangNumber,GroupNumber,Avatar,
			ServicesNumber,ReturnData)   
                  values(@UserNumber,@NickName,@LiangNumber,@GroupNumber,@Avatar,
			@ServicesNumber,@ReturnData)  
                     SELECT @CurrentIndex=@NextIndex+1;  
     END  
     select * from #t  
     drop table #t  
     end  

[Proc_#UsersInfo_GetDataInfo] '1036|1039|1035|','|'
결실
1035 NULL 65484 3 NULL 2 2 | 토박이 부자 | 1 | [tcz] | 1 회 충전 5 만 \ #
1036 test 1 10361036 NULL NULL 1 | 2 | 3 | 대형 | 1 | [dk] | 100 만 가상 화 폐 를 사용 합 니 다 \ # 2 | 토박이 부자 | 1 | [tcz] | 5 만 원 을 한꺼번에 충전 합 니 다 \ # 1 | 귀족 | 1 | [gz] | 소비 가 1 만 원 을 초과 합 니 다 \ #
1039 test 1037 1 NULL 2 | 3 | 대형 | 1 | [dk] | 100 만 가상 화 폐 를 사용 합 니 다 \ # 2 | 토박이 부자 | 1 | [tcz] | 5 만 원 을 한꺼번에 충전 합 니 다 \ #
상기 조작 은 프로그램 과 데이터 베이스 간 의 링크 빈 도 를 낮 추 었 으 나 데이터 뱅 크 의 연산 량 과 데이터 전송 량 을 증가 시 켰 다.
마지막 으로 우리 팀 은 저장 과정 을 데이터베이스 에서 마지막 열 에 있 는 데이터 (@ ReturnData) 를 읽 게 하 는 것 을 포기 하고 이 데이터 시트 에 있 는 데 이 터 를 한꺼번에 프로그램 메모리 에 읽 은 다음 프로그램 에서 번호 집합 (마지막 두 번 째 열) 에 따라 분석 했다.

좋은 웹페이지 즐겨찾기