我正在尝试优化我的T-SQL存储过程。它用于根据VIN(17个字符的字母数字字符串)提取记录;通常人们只知道一些数字 - 例如。第一个数字可以是'1','2'或'J';第二个是'H',但第三个可能是'M'或'G';等等。
这导致了一个非常复杂的查询,其WHERE
子句类似于
WHERE SUBSTRING(VIN,1,1) IN ('J','1','2')
AND SUBSTRING(VIN,2,1) IN ('H')
AND SUBSTRING(VIN,3,1) IN ('M','G')
AND SUBSTRING(VIN,4,1) IN ('E')
AND ... -- and so on for however many digits we need to search on
我正在查询的表是 huge (数百万条记录),因此我正在运行的具有此类WHERE
子句的查询可能需要小时如果有多个数字被搜索,则运行,即使我只请求前3000条记录。我觉得必须有一种方法来使这个子串字符匹配运行得更快。几小时是完全不可接受的;我想在几分钟内运行这些类型的查询。
遗憾的是,我对数据库没有任何编辑权限,所以我无法添加索引或类似内容;我所能做的就是更改我的存储过程(虽然我可以尝试让DBA修改表格。)
答案 0 :(得分:3)
您可以使用
WHERE VIN LIKE '[J12]H[MG]E%'
至少应该在JH%
,1H%
和2H%
范围内找到3个索引,而不是完整扫描。
编辑虽然在本地测试我发现它没有进行多次索引搜索,因为我希望它将上面的内容转换为更大范围VIN >= '1' and VIN < 'K'
上的单个搜索,并带有残差谓词评估LIKE
我不确定它是否会为更大的表格做到这一点,但是否则可能值得尝试用
来鼓励这个计划WHERE (VIN LIKE 'JH%' OR VIN LIKE '1H%' OR VIN LIKE '2H%')
AND VIN LIKE '[J12]H[MG]E%'
答案 1 :(得分:2)
您可以使用LIKE关键字
SELECT
*
FROM Table
WHERE VIN LIKE '[J12]H[MG]E%'
这甚至允许您使用语句中的[^ A]来处理他们知道第二个字符不是“A”的实例,例如:
WHERE VIN LIKE '[J12][^A][MG]E%'
答案 2 :(得分:1)
我喜欢LIKE
答案,但这是另一种选择(特别是如果你的输入并不总是相同的话)。
我会在更小的临时表上进行一系列查询(是的,我爱上临时表 - 起诉我。)
所以我会做类似
的事情SELECT [Fields]
INTO #tempResultsFirstTwoDigits
FROM VIN
WHERE [Clause]
然后逐位向下移动链,直到您搜索了每个提供的字符。所以你可以这样做:
if len(@input) > 2
SELECT [Fields]
INTO #tempResultsThreeDigits
FROM VIN
WHERE Substring(VIN, 3, 1) = Substring(@input, 3, 1)
//NOTE: That where clause might be sped up by initializing a variable at
// the beginning of the SP for each character you got.
Else Select * From #tempResultsFirstTwoDigits
GOTO Stop //Where "Stop" just defines the end of the SP to skip any further checks
同样,LIKE
可能是一个更好的答案,但我会尝试这两种方法并对它们进行基准测试。