在 SQL Server 中,索引视图是一个充满限制的地狱景观。但我需要一个。我有一个格式化程序 SQLCLR 函数,它创建一个域键的美化版本 - 用户希望能够搜索该美化版本的子字符串。所以我需要一个持久计算列或物化视图的全文索引。
但是,格式化程序依赖于存储在多个表中的数据。
所以这适用于视图,但不适用于持久计算列,因为它们无法从多个表中查询。
我的 SQLCLR 方法是精确且确定性的,因此它应该可以在索引视图中使用,但索引视图的索引键中不能有 SQLCLR。
我可以使用 T-SQL 函数重新实现我的格式化程序FORMAT
......但FORMAT
也与索引视图不兼容。
索引视图可以做任何事情吗? 曾经?
如果有人可以向我推荐一个关于最佳实践的好文档,我对“使用触发器滚动你自己的物化视图”方法持开放态度。上次我尝试时,它失控了,插入和更新的代码与初始化之间存在大量重复。
是否有某种方法可以在不使用物化/索引视图或持久计算列的情况下对几百万行的计算数据进行高性能文本搜索?
格式化程序不执行数据访问。但是,我需要输入格式化程序以使其有用的数据将来自多个表(具有良好的常规连接),因此我无法使用持久计算列解决此问题。我无法键入 SQLCLR 列,因此无法在全文索引中使用它。
我以为这很简单。持久列和索引视图旨在执行写入计算,并正确实现观察者模式,以便对其依赖关系的更改反映在计算值上。
当您将索引视图视为一种解决方案时,它实际上有点悲惨,只是发现您的用例遇到了索引视图的众多限制之一(我在看着你,
LEFT JOIN
)。没错,您不能在索引视图的索引键中包含 SQLCLR。但是,您可以将其包含在
SELECT
视图定义列表中,这会将值保存到磁盘。因此,您至少可以避免在从表中读取时即时计算值的成本。在 AdventureWorks2014 示例数据库中,我在命名良好的
Person.Person
表上创建了这个视图:注意:我懒得写自己的 CLR 函数,所以这个来自这个 Q&A。
我可以通过将其聚集在以下位置来使其成为索引视图
BusinessEntityID
:在表中查找一组特定的行会产生索引扫描(执行计划链接)。请注意缺少
Compute Scalar
通常用于生成哈希值的运算符。由于哈希在索引视图中被持久化到磁盘,因此没有必要:我不得不使用
NOEXPAND
提示让它使用视图。您会注意到计划中的警告是由于扫描了整个表以找到这些值,因为没有键控索引
FirstNameHash
。不幸的是,尝试在此持久值上创建非聚集索引失败:
这是因为 SQL Server不信任我们:
我想全文索引也存在同样的限制,尽管我没有尝试过。
正如您在自己的帖子中提到的,从这一切中得出的结论是,您有点被困在这里。实际上,您唯一的选择是:
无法在非确定性列上创建全文索引。
Search
尝试对索引视图中定义的列进行全文索引时产生了该错误,如下所示:那里引用的函数来自SQL# CLR 库,并且在免费版本中可用。它们与函数的功能相匹配
FORMAT
,这在索引视图中根本不允许。然而,全文搜索似乎不太可能是您所需要的。它不适用于前导通配符搜索或涉及非单词的一般字符串匹配。正如文档所说:
如果您需要快速的前导通配符和/或非语言搜索,并且T-SQL 内置函数在测试后表现不佳,一种替代方法是使用 n-gram,正如我在Trigram Wildcard String Search 中所述SQL 服务器。
那篇文章包含一个完整的实现,包括简单的触发器来保持数据源(例如上面的索引视图)在需要时始终与 n-gram 同步。如果您不需要实时同步,您可能会发现每隔一段时间完全重建 n-gram 对您的用户来说已经足够好,以至于不需要触发器(尽管它们很轻量级)。