[英]How can I improve the speed of a SQL query searching for a collection of strings
我有一个名为T_TICKET
的表,该表的T_TICKET
CallId varchar(30)
。
这是我的数据的示例:
CallId | RelatedData
===========================================
MXZ_SQzfGMCPzUA | 0000
MXyQq6wQ7gVhzUA | 0001
MXwZN_d5krgjzUA | 0002
MXw1YXo7JOeRzUA | 0000
...
我正在尝试查找与CallId
集合匹配的记录。 像这样:
SELECT * FROM T_TICKET WHERE CALLID IN(N'MXZInrBl1DCnzUA', N'MXZ0TWkUhHprzUA', N'MXZ_SQzfGMCPzUA', ... ,N'MXyQq6wQ7gVhzUA')
我有200到300个CallId
使用该查询一次查询。 该查询大约需要35秒才能运行。 我可以对表结构,列类型,索引或查询本身做些什么来提高此查询的性能?
T_INDEX
当前大约有300,000行。 CallId
不是唯一的。 而且RelatedData
不是唯一的。 我在CallId
上也有一个索引(非聚集)。
我知道SQL的基础知识,但我不是专业人士。 我想到的一些事情是:
CallId
的类型从varchar
更改为char
。 CallId
的长度(它的长度为30,但实际上,现在,我仅使用15个字节)。 我还没有尝试过这些方法,因为它需要更改实时生产数据。 而且,我不确定他们是否会做出重大改进。
这些选择中的任何一个都会带来重大改进吗? 或者,还有其他我可以做的事情来使它更快地执行吗?
首先,请确保类型相同VARCHAR()
或NVARCHAR()
。 然后,添加一个索引:
create index idx_t_ticket_callid on t_ticket(callid);
如果类型兼容,则SQL Server应使用索引。
您的表就是我们所谓的堆(没有聚集索引的表) 。 这种表仅适合于数据加载和/或作为临时表。 我建议您将表转换为具有集群键。 一个好的集群密钥应该是唯一的,静态的,狭窄的,不可为空的并且不断增长的(例如int
/ bigint
身份数据类型)。
堆的另一个缺点是,当您的表上有很多UPDATE
/ DELETE
时,由于转发记录,它将减慢SELECT
速度。 Paul Randal引用转发记录:
如果转发记录出现在堆中,则当记录定位器指向该位置时,存储引擎会到达该位置并说,哦,记录实际上不在这里-它在那儿! 然后,它必须执行另一个(可能是物理的)I / O才能进入具有转发记录的页面。 这可能导致堆效率不及等效的聚集索引。
最后,请确保您在SELECT
上定义了所有列。 避免使用SELECT *
。 我猜您在执行查询时遇到table scan
。 您可以做的是在索引的SELECT
上INCLUDE
所有列列表,如下所示:
CREATE INDEX [IX_T_TICKET_CallId_INCLUDE] ON [T_TICKET] ([CallId]) INCLUDE ([RelatedData]) WITH (DROP_EXISTING=ON)
事实证明,实际上有一种方法可以在不更改任何数据类型的情况下大大优化我的查询。
该查询:
SELECT * FROM T_TICKET
WHERE CALLID IN(N'MXZInrBl1DCnzUA', N'MXZ0TWkUhHprzUA', N'MXZ_SQzfGMCPzUA', ... ,N'MXyQq6wQ7gVhzUA')
正在使用NVARCHAR
类型作为输入参数(N'MXZInrBl1DCnzUA', N'MXZ0TWkUhHprzUA'...)
。 正如我在问题中指定的那样, CallId
是VARCHAR
。 Sql Server将表的每一行中的CallId
转换为NVARCHAR
类型以进行比较,这花费了很长时间(即使我在CallId
上有索引)。
我能够通过不将参数类型更改为NVARCHAR
来对其进行优化:
SELECT * FROM T_TICKET
WHERE CALLID IN('MXZInrBl1DCnzUA', 'MXZ0TWkUhHprzUA', 'MXZ_SQzfGMCPzUA', ... ,'MXyQq6wQ7gVhzUA')
现在,它不需要花费30秒钟来运行,而仅需大约.03秒钟。 感谢所有的投入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.