Spe*_*und 6 sql-server sql-server-2014
我有一个在工作中经常出现的案例。我有很多表使用 4 个字符串作为外键:G191
TheG
是一种类别,the19
是年份,the1
是一个实例。获取类别的所有行G
是我们经常做的事情。通常喜欢:
SELECT * FROM [Table]
WHERE Left([ID], 1) = 'G'
Run Code Online (Sandbox Code Playgroud)
有一种方法可以在不操作字符串的情况下获得这种效果,方法是加入定义了该类别的表:
SELECT * FROM [Table]
JOIN [Categories] ON [Table].CategoryID = [Categories].CategoryID
WHERE [Categories].Letter = 'G'
Run Code Online (Sandbox Code Playgroud)
我的同事坚持认为第一种方法的性能更高,并且因为我采用第二种方法而对我翻白眼。
哪一个更好?通过另一个表加入是否真的比检查字符串的第一个字符增加了更多的工作?
Eri*_*ing 16
一般来说,你的模式是一个更好的主意。
不过,性能将取决于索引、谓词选择性和表大小。
你的模式是一个更好的主意的原因归结为 SARGability 的概念,如果你的搜索参数可以用作搜索谓词,甚至完全推送谓词,这是一个花哨的词(即在访问一个指数)。
这可能会在连接和 where 子句中造成伤害的一些示例是:
当你做这样的事情时,你的查询最终可能会产生各种不良的副作用:
您正在寻找的 SARGable 选项包括:
WHERE [ID] LIKE 'G%'
或者
WHERE [ID] >= 'G' AND [ID] < 'H'
另一种解决方案是在您正在搜索的表中添加一个计算列:
ALTER TABLE [Table]
ADD Lefty AS Left([ID], 1);
CREATE INDEX ix_whatever
ON [Table] (CategoryID , Lefty);
Run Code Online (Sandbox Code Playgroud)
虽然就像我之前说的,对于较小的表,性能差异可能并不显着。
也可能不会使用此索引,因为您的示例查询选择了所有表列,而此索引未涵盖它们。但那是另一天的故事。