2017-11-20 16 views
0

에 의해 주문을 제거 나는 다음과 같은 테이블이 다음 DIALPLAN 테이블 (예를 들어 모든 전화 번호 접두사 (100K 행) Prefixe 접두사 값을 포함하는 필드를 포함쿼리 최적화는 SQL Server 인스턴스에

CREATE TABLE [dbo].[DIALPLAN](
    [IdDialPlan] [int] IDENTITY(1,1) NOT NULL, 
    [Prefixe] [varchar](500) NOT NULL, 
    [Type] [varchar](255) NOT NULL, 
    [Country] [varchar](255) NOT NULL, 
    [Description] [varchar](255) NOT NULL, 
CONSTRAINT [PK_TMP_DIALPLAN] PRIMARY KEY CLUSTERED 
(
    [IdDialPlan] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY], 
CONSTRAINT [CK_TMP_DIALPLAN_UNIQUE] UNIQUE NONCLUSTERED 
(
    [Prefixe] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

CREATE TABLE [dbo].[CALLS](
    [uniqueid] [varchar](150) NULL, 
    [accountcode] [varchar](20) NULL, 
    [OutTel] [varchar](80) NULL, 
    [lastapp] [varchar](80) NULL, 
    [lastdata] [varchar](200) NULL, 
    [CallLocalTime] [datetime] NULL, 
    [answer] [datetime] NULL, 
    [CallEnd] [datetime] NULL, 
    [duration] [int] NULL, 
    [CallDuration] [int] NULL, 
    [disposition] [varchar](20) NULL, 
    [Destination] [text] NULL, 
    [Asterisk] [varchar](20) NULL, 
    [Endreason] [varchar](20) NULL, 
    [CLI] [varchar](80) NULL 
) 

을 캐나다 알버타는 1403, 프랑스 모바일 부이 그스는 33665)와 CALLS 테이블에는 전화 통화가 포함되어 있습니다 (항상 1K 행의 배치를 선택). 다음 쿼리의 목적은 각 전화 번호에 맞는 접두어를 찾는 것입니다 (CALLS 테이블의 OutTel 필드). 올바른 접두사는 전화 번호와 일치하는 가장 긴 접두사입니다.

-- Solution 1 4200ms : Sort 40% Top 10% 
SELECT TOP 1000 SUBSTRING(OutTel,3,LEN(OutTel)), FN.IdDialPlan, FN.Description 
    FROM [dbo].[CALLS] 
    CROSS APPLY (SELECT TOP 1 IdDialPlan, Description FROM [dbo].[DIALPLAN] dp WHERE dp.Prefixe = LEFT(SUBSTRING(OutTel,3,LEN(OutTel)),LEN(dp.Prefixe)) ORDER BY LEN(Prefixe) DESC) AS FN 


-- Solution 2 3400ms : Sort(Join) 50% 
SELECT TOP 1000 SUBSTRING(calls.OutTel,3,LEN(calls.OutTel)), dp.IdDialPlan, dp.Description 
FROM [dbo].[CALLS] calls LEFT JOIN [dbo].[DIALPLAN] dp ON dp.Prefixe = LEFT(SUBSTRING(calls.OutTel,3,LEN(calls.OutTel)),LEN(dp.Prefixe)) 

더 짧은 시간에 동일한 결과를 얻을 수있는 다른 방법이 있습니까?

EDIT 1 :

enter image description here

EDIT 2 :

enter image description here

이 용액 2 실행 계획은 다음과
이 용액 1 실행 계획이다
몇 가지 샘플 데이터가 있습니다
만 표시 목적으로

OutTel 
---------------- 
0033170448508 
0033155373050 
0021620383555 
0016465699156 
00390689971917 

DIALPLAN 테이블

IdDialPlan Prefixe   Type  Country   Description 
----------- --------------- -------- --------------- ------------------------------ 
471   1646   Fixed United States United States - New York 
32284  331    Fixed France   France - Paris City 
32318  3317044   Fixed France   France - Paris City 
34658  216    Fixed Tunisia   Tunisia 
34659  21620   Mobile Tunisia   Tunisia - Mobile - Tunisiana 
35571  3906   Fixed Italy   Italy - Rome 

감사에 대한 87,610,413,210 테이블 OutTel 필드.

+0

'DIALPLAN'의'Prefixe'와'CALLS'의'OutTel'의 색인을 생성 했습니까? – Monah

+1

실행 계획이 있습니까? –

+0

@Monah는'DIALPLAN'의'Prefixe '에'NONCLUSTRED INDEX'을 가지고 있지만'CALLS'의'Outtel'에는 들어 있지 않습니다. – Fourat

답변

0

함수 조인으로 인해 인덱스가 항상 탐색되기 때문에 구조 변경을해야하는 것처럼 보입니다. 이러한 정렬은 TOP 연산자입니다.

top (1) 대신 max()를 사용해도되지만 거기에 설명이 붙어서 작동하지 않습니다.

클러스터 된 인덱스를 사용하여 2 개의 테이블 (잘하면 저장 프로 시저이고 Entity Framework가 아닌)을 채우는 것을 통해 채워질 매핑 테이블을 만들 수 있으므로 열을 미리 정렬 할 수 있지만 삽입 속도가 느려집니다 업데이트합니다. 또한 인덱스 스캔 작업을 해결할 수 있습니다.