视图优化中的子查询

Sub-query within a view optimization

我有一个从两个表 CallCaller 读取的视图,这两个表是并行的,因为它们以相同的 ID 为键(即获取呼叫的呼叫者信息,您加入 Call.id = Caller.id)。我有一个跨越这两个表的视图 return 关于任何特定呼叫或一组呼叫的综合信息。

但我在该视图中有一个子查询,用于确定呼叫者是否已被回叫(定义为在该呼叫后存在另一个对相同 phone 号码的呼叫,状态为的完成)。此子查询使视图的查询速度极慢,但我不确定包含此信息的更好方法是什么。以下是相关的 DDL,想法?

编辑:如果添加了一些索引,这个查询是否会很好,或者是否有更有效的方式来构造查询本身?

CREATE TABLE [CALL]
(
    ID VARCHAR(64) PRIMARY KEY, --this is a legacy system, I know varchar(64) isn't an efficient primary key
    CALLDATE DATETIME,
    STATUS BIT --1 = Complete, 0 = Incomplete
)

CREATE TABLE [CALLER]
(
    ID VARCHAR(64) PRIMARY KEY,
    PHONENUMBER VARCHAR(10),
    FIRSTNAME VARCHAR(50),
    LASTNAME VARCHAR(50)
)

CREATE VIEW [CALLVIEW] AS
SELECT
    CALL.ID AS CALLID,
    CALL.CALLDATE AS CALLDATE,
    CALL.STATUS AS CALLSTATUS,
    CALLER.PHONENUMBER AS PHONENUMBER,
    CALLER.FIRSTNAME AS FIRSTNAME,
    CALLER.LASTNAME AS LASTNAME,
    CAST(CASE WHEN EXISTS (SELECT TOP 1 1
                           FROM [CALL] CALL2
                           INNER JOIN [CALLER] CALLER2 ON CALL2.ID = CALLER2.ID
                           WHERE CALLER2.PHONENUMBER = CALLER.PHONENUMBER
                           AND CALL2.CALLDATE > CALL.CALLDATE
                           AND CALL2.STATUS = 1) THEN 1 ELSE 0 END AS BIT) AS CALLEDBACK
FROM
    [CALL]
    INNER JOIN [CALLER] ON [CALL].ID = [CALLER].ID

编辑:从执行计划中我注意到,到目前为止,查询中最昂贵的部分如下:

聚集索引查找

谓词:CALL2.CALLDATE > CALL.CALLDATE AND CALL2.STATUS = 1

对象:[CALL].[PK_CALL] CALL2(所以用的是主键索引)

输出列表:[CALL].CALLDATE, [CALL].STATUS

寻找谓词:[CALL].id = 标量运算符([CALLER].id)

索引查找

对象:[CALLER].[IX_PHONENUMBER] CALLER2(所以它使用了正确的索引但仍然很昂贵?)

输出列表:[CALLER].ID

寻找谓词:[CALLER].PHONENUMBER = 标量运算符([CALLER].PHONENUMBER)

首先,尝试使用Database Engine Tuning Advisor,它会告诉您是否需要创建一些索引。

无论如何,我会这样做:

  • 验证您在 CALL.ID 和 CALLER.ID 上确实有一个 CLUSTERED 索引(作为遗留系统,也许您有 PK 但有人删除了索引)
  • 创建非聚集索引:
    • CALLER.PHONENUMBER
    • CALL.CALLDATE
    • CALL.STATUS
  • Reorganize/Rebuild 索引
  • 更新统计数据