SELECT * WHERE VarCharColumn IN (...) 优化

Jer*_*oyd 6 index sql-server-2008 sql-server

我有一个包含 3000 个字符串的列表,我将它们(一次 20 个)传递到参数化的 IN 子句中。它绝对没有得到我希望每次执行 500 毫秒的结果。

该列是一个索引。你知道比这更好的方法吗:

SELECT * FROM [ohb].[dbo].[MasterUrls] WITH (NOLOCK) WHERE Hash 
IN(@p0,@p1,@p2,@p3,@p4,@p5,@p6,@p7,@p8,@p9,@p10,@p11,@p12,@p13,@p14,@p15,@p16,@p17,@p18,@p19)
Run Code Online (Sandbox Code Playgroud)

3000 个列表需要 3 到 5 分钟。我真的需要把它缩短到大约 30 秒。这可能吗?

我在具有 24 gigs RAM 的服务器上使用 MSSQL 2008 R2,并在 6HDD (@15k/rpm) RAID 10 ISCSI 上运行双 8 核 NUMA Xeons @2.4Ghz。

该表有 140 万行,索引为非聚集索引。

执行计划将索引扫描显示为总执行的 90%。

gbn*_*gbn 7

SELECT *即使索引了哈希,也会使索引的任何最佳使用无效(它没有覆盖)。因此,您的索引扫描很可能在聚集索引上进行。

就个人而言,我会从

  • 将 3000 个搜索值放入带有索引的表中
  • 编辑:根据玛丽安的评论,这可以在列表或表格中传递
  • 在 JOIN、IN、EXISTS 中的任何一个中使用它(通常相同的计划)
  • 使用 Hash 确保我在 MasterUrls 上的索引适合并涵盖 col1、col2、col3

就像是

CREATE TABLE #foo (Hash ...)
INSERT #foo...
CREATE INDEX IX_FOO ON #foo (hash)

--either
CREATE NONCLUSTERED INDEX IX_Hash ON MasterUrls (hash) INCLUDE (col1, col2, col3)
--or    
CREATE CLUSTERED INDEX IXC_Hash ON MasterUrls (hash)

SELECT col1, col2, col3
FROM [ohb].[dbo].[MasterUrls] M
JOIN
#foo F ON M.Hash = F.Hash
Run Code Online (Sandbox Code Playgroud)

  • 我要补充一点,如果您需要从应用程序发送参数列表,您可以将它作为一个字符串发送,您可以使用函数或表变量将其拆分为多个部分(我看到您正在使用 SQL 2008,所以没关系)然后继续gbn的想法。 (3认同)

Jer*_*oyd -1

实际上,我以更快的无 SQL 方式解决了这个问题。

在这之前的另一步骤中,我从表中获取 URL 和 ID(而不仅仅是 URL,我将对其进行散列以进行查找 - 这个问题),将它们保存在内存中,然后保存在 FS 上(以防内存失败) -- 当然是异步的),然后当需要进行查找时,我从存储在内存/FS 中的数据中读取数据。

现在,该过程平均需要不到 5 秒的时间来查找和更新(本问题之后的步骤)3000 行的数据。平均时间比 240 秒好得多。

  • 我理解这种挫败感。这就是为什么我认为您应该更好地倾听 Sandy 和 GBN 的问题,并通过提供表的架构和一些示例数据来帮助我们为您提供帮助。我确信这个问题有更好的解决方案。您只需向我们提供更多信息即可。通过仅提供 Select 语句,我们不能说比我们刚才已经说的更多的内容。 (2认同)