SQL Server,使用正确的索引进行查询,但仍然很慢

SQL Server,使用正确的索引进行查询,但仍然很慢,sql,sql-server,indexing,Sql,Sql Server,Indexing,我的问题如下: SELECT 1 FROM [Call] INNER JOIN [Caller] ON [Call].callerId = [Caller].id WHERE [Call].[phoneNumber] = @phoneNumber AND [Caller].callerType = @callerType AND [Call].[time] > @time AND [Call].[status] = @status AND [Call].[type] <> @t

我的问题如下:

SELECT 1
FROM [Call]
INNER JOIN [Caller] ON [Call].callerId = [Caller].id
WHERE [Call].[phoneNumber] = @phoneNumber
AND
[Caller].callerType = @callerType
AND
[Call].[time] > @time
AND
[Call].[status] = @status
AND
[Call].[type] <> @type
CREATE INDEX IX_callerId_time_phonenumber_status_type 
ON dbo.[Call]
(
    [callerId] ASC,
    [time] ASC,
    [phoneNumber] ASC,
    [status] ASC,
    [type] ASC
)
Predicate:
[Call].[status] = 10 AND [Call].[type] <> 10

Object:
[Call].[IX_callerId_time_phonenumber_status_type]
我在执行计划中注意到,我查询的90%成本如下:

SELECT 1
FROM [Call]
INNER JOIN [Caller] ON [Call].callerId = [Caller].id
WHERE [Call].[phoneNumber] = @phoneNumber
AND
[Caller].callerType = @callerType
AND
[Call].[time] > @time
AND
[Call].[status] = @status
AND
[Call].[type] <> @type
CREATE INDEX IX_callerId_time_phonenumber_status_type 
ON dbo.[Call]
(
    [callerId] ASC,
    [time] ASC,
    [phoneNumber] ASC,
    [status] ASC,
    [type] ASC
)
Predicate:
[Call].[status] = 10 AND [Call].[type] <> 10

Object:
[Call].[IX_callerId_time_phonenumber_status_type]
所以它使用了正确的索引,但我的性能仍然很差。有什么想法吗?

Predicate[Call].[time]>@time是不可选择的,但是索引的结构迫使SQL Server将其优先于其他一些可能更具选择性的条件。它可能会选择为每个被调用方扫描一大块索引。这样重新排序索引可能会提高此特定查询的性能:

CREATE INDEX IX_callerId_time_phonenumber_status_type 
ON dbo.[Call]
(
    [callerId] ASC,
    [phoneNumber] ASC,
    [status] ASC,
    [time] ASC,
    [type] ASC
)

由于不知道Time是真正的Time数据类型还是varchar数据类型,我建议使用以下索引

CREATE NONCLUSTERED INDEX IX_callerId_time_phonenumber_status_type
ON [dbo].[Call] ([PhoneNumber],[Status],[Time],[Type])

您是否排除了参数嗅探?想知道优化器是否在一些不利于值的问题上卡住了


这是我最喜欢的文章

是索引扫描,对吗?谓词中的不等式可能导致谓词不可争论。简单地更改为call.type>10或call.type<10可能会使其成为搜索。仅使用时间列遍历树。没有任何东西可以缩小遍历的范围——后面的所有内容都只是一个过滤器谓词。您几乎总是应该首先按相等值而不是按范围进行索引。@SeanLange它实际上已经是一个搜索了。@SeanLange,我将它改为小于或大于,但它被编译回了!=根据执行计划,这个表有超过1亿行可以追溯到10年前,所以我认为时间的优先级应该更高,特别是因为查询主要是查询最近的数据。考虑到这一点,你认为索引应该是什么样的?@ghettojoe,可能值得尝试两种方法。不过,如果非要我猜的话,我还是会把钱放在我建议的订单上。它最终应该扫描更少的索引行,但这些行的分布范围更广,这将缓解这种情况。也请注意,我所说的只是对这个查询的影响。另一个链接