查询优化摆脱了Order by

时间:2017-11-20 17:58:11

标签: sql sql-server sql-execution-plan

在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
)

DIALPLAN表包含所有电话号码前缀(100K行),字段Prefixe包含前缀值(例如加拿大艾伯塔省1403或法国移动Bouygues 33665)和{{1} } table包含电话呼叫(始终选择一批1K行)。以下查询的目的是为每个电话号码找到正确的前缀(CALLS表的字段OutTel)。正确的前缀是与电话号码匹配的最长前缀:

CALLS

有没有其他方法可以在更短的时间内获得相同的结果?

编辑1:
这是解决方案1的执行计划:

enter image description here

这是解决方案2的执行计划:

enter image description here

编辑2:
这是一些示例数据
-- 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)) CALLS字段仅用于显示目的

OutTel

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

DIALPLAN

感谢。

1 个答案:

答案 0 :(得分:0)

看起来您需要进行结构更改,因为您的索引总是会因为函数的连接而被搜索,而这些类型是您的TOP运算符。

您可以尝试使用max()而不是top 1,但是你可以在那里使用Description,因此它不起作用。

您可以创建一个映射表,该表将通过聚集索引填充您的2个表(希望它是一个存储过程而不是实体框架)填充,因此它会预先排序您的列,但它会减慢您的插入和更新。它还可以解决您的索引扫描操作。