【问题标题】:Query optimization get rid of Order by查询优化摆脱Order by
【发布时间】:2017-11-20 17:58:11
【问题描述】:

在 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 或法国移动布依格的 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))

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

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

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

编辑 2:
这是一些示例数据
CALLS table OutTel 字段仅用于显示目的

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

谢谢。

【问题讨论】:

  • 您是否为DIALPLAN 中的Prefixe 列和CALLS 中的OutTel 编制了索引?
  • 你有执行计划吗?
  • @Monah for Prefixe in DIALPLAN 我确实有一个NONCLUSTRED INDEX,但在Outtel CALLS 中没有Outtel
  • @RuslanTolkachev 我编辑了问题。
  • 一些样本数据预期结果可能会极大地帮助这个问题。

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


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2011-05-13
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    相关资源
    最近更新 更多