我想要这样的查询:
SELECT TOP 60 lcode
FROM LessonChart
WHERE lcode LIKE '1%'
但SQL Server表示将int转换为varchar并不好,关键字“LIKE”效率不高......
我应该怎么做而不是这段代码?
答案 0 :(得分:3)
核心问题 - 以及警告 - 即使lcode LIKE '1%'
在SQL Server(it accepts the syntax and perform an implicit cast)中有效,但在此过程中,查询不再是Sargable。这意味着由于隐式转换,INT列上的任何索引都不能在LIKE操作中使用。
..如果DBMS引擎可以利用索引来加速查询的执行,则认为查询是可搜索的。该术语源于搜索ARGument ABLE的收缩。
这种能够使用索引的损失并不特定于此CAST-then-then-LIKE操作,它也会影响conditions that use the column in other expressions, such as math。虽然警告很好,但SQL Server相当有限,它会直接抱怨哪些查询 - 慢查询可能只是一个缓慢的查询。
如果这种索引丢失的使用不是(并且不会成为)问题,因为只有相对较少的行应用了条件(例如,数据很少或查询已经减少)考虑到合理数量的候选人,然后不要担心 - 但是请继续阅读,因为无论如何都可能需要改变。请参阅Display and Save Execution Plans,了解实际数据库设计/增长的知识,可以帮助您做出决定。
如果无法使用索引是一个问题或将是一个问题(因为谓词应用了数万甚至数百万行),或者如果寻找简单清理查询的可能方法,那么:
Evalaute设计。它真的是整数值(例如金额)还是标识符只使用数字(例如电话号码或邮政编码)?
如果是后者,则考虑将设计更改为CHAR / VARCHAR并添加索引。这将修复 sargability问题和使列/类型更好地代表信息。
再次评估设计。这是否领先" 1"表示与标识符的其余部分分开的信息?如果是这样,可以/应该将其标准化为单独的列吗?
如果将它分开是有意义的,那么创建一个单独的可索引(位?)列并继续。
即使不应该分开"例如,可以使用persisted computed column。 (虽然标识符/ lcode现在包含冗余信息,但不会直接查询。)
计算列是根据可以使用同一表中其他列的表达式计算的。通过将计算列标记为PERSISTED,您可以在计算列上创建一个确定性的索引。
如果设计正确,以致上述两者都不适用且查询必须能够出于性能原因使用索引,则编写查询以便它可以使用索引。这是一个 能够使用指数的kludge(并注意它是多少的kludge,见上文)。
WHERE lcode = 1
OR lcode BETWEEN 10 AND 19
OR lcode BETWEEN 100 AND 199
-- etc
对于少量行而言,这无关紧要,但随着谓词中涉及的行数增加(使用甚至是丑陋的)可索引查询,可以避免因必须加载/扫描过多而导致的大量执行惩罚行数。