首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >查询优化摆脱Order by

查询优化摆脱Order by
EN

Stack Overflow用户
提问于 2017-11-21 01:58:11
回答 1查看 61关注 0票数 0

在SQL Server实例上,我有以下表格:

代码语言:javascript
复制
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,对于法国移动布伊格为33665 ),而CALLS表包含电话呼叫(始终选择一批1K行)。以下查询的目的是查找每个电话号码的正确前缀( CALLS表的字段OutTel )。右边的前缀是与电话号码匹配的最长前缀:

代码语言:javascript
复制
-- 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))

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

编辑1:

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

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

编辑2:

下面是一些示例数据

CALLSOutTel字段仅用于显示目的

代码语言:javascript
复制
OutTel
----------------
0033170448508
0033155373050
0021620383555
0016465699156
00390689971917

DIALPLAN

代码语言:javascript
复制
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

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2017-11-21 22:39:53

看起来你需要做一些结构上的改变,因为你的索引总是因为函数的连接而被搜索,而那些排序是你最常用的运算符。

你可以尝试使用max()而不是top 1,但是你在那里有描述,所以它不能工作。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47398293

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档