Pxt*_*xtl 2 sql-server materialized-view sql-clr
在 SQL Server 中,索引视图是一个充满限制的地狱。但我需要一个。我有一个格式化程序 SQLCLR 函数,它创建域密钥的美化版本 - 用户希望能够搜索该美化版本的子字符串。因此,我需要持久计算列或物化视图上的全文索引。
但是,格式化程序依赖于存储在多个表中的数据。
因此,这适用于视图,但不适用于持久计算列,因为它们无法从多个表进行查询。
我的 SQLCLR 方法是精确且确定的,因此它应该适合在索引视图中使用,但索引视图的索引键中不能包含 SQLCLR。
我可以使用 T-SQL 函数重新实现我的格式化程序FORMAT...但也与索引视图不兼容FORMAT。
索引视图可以做任何事情吗? 曾经?
如果有人可以向我推荐一份关于最佳实践的好文档,我对“使用触发器滚动你自己的物化视图”方法持开放态度。上次我尝试时,它失去了控制,并且插入和更新代码与初始化之间存在巨大的重复。
我是否缺少某种方法来对几百万行的计算数据进行高性能文本搜索,而不使用物化/索引视图或持久计算列?
格式化程序不执行数据访问。但是,我需要输入格式化程序以使其有用的数据将来自多个表(具有良好的常规联接),因此我无法使用持久计算列来解决此问题。我无法为 SQLCLR 列设置键,因此无法在全文索引中使用它。
我以为这很简单。持久列和索引视图旨在在写入时执行计算,并正确实现观察者模式,以便对其依赖项的更改反映在计算值上。
\n\n\n索引视图可以做任何事情吗?曾经?
\n
LEFT JOIN当您将索引视图视为一种解决方案时,却发现您的用例遇到了索引视图的众多限制之一(我正在看着您, ),这实际上有点悲惨。
你是对的,你不能将 SQLCLR 包含在索引视图的索引键中。但是,您可以将其包含在SELECT视图定义的列表中,这会将值保留到磁盘。因此,您至少可以避免在从表中读取数据时动态计算值的成本。
在 AdventureWorks2014 示例数据库中,我在名称恰当的Person.Person表上创建了此视图:
CREATE OR ALTER VIEW dbo.PersonWithHashForSomeReason\nWITH SCHEMABINDING\nAS\nSELECT \n BusinessEntityID,\n PersonType,\n dbo.SpookyHash(CONVERT(binary(50), FirstName)) AS FirstNameHash\nFROM Person.Person\nGO\nRun Code Online (Sandbox Code Playgroud)\n\n注意:我懒得写自己的 CLR 函数,所以这个来自这个 Q&A。
\n\n我可以通过将其聚集在以下位置来使其成为索引视图BusinessEntityID:
CREATE UNIQUE CLUSTERED INDEX CX_BusinessEntityID \nON dbo.PersonWithHashForSomeReason (BusinessEntityID);\nGO\nRun Code Online (Sandbox Code Playgroud)\n\n在表中查找特定的行集会产生索引扫描(执行计划链接)。请注意,缺少Compute Scalar通常用于生成哈希值的运算符。由于散列在索引视图中持久保存到磁盘,因此没有必要:
SELECT BusinessEntityID, FirstNameHash \nFROM dbo.PersonWithHashForSomeReason WITH (NOEXPAND)\nWHERE FirstNameHash = 0x910C426C533F2C0AAF350158331E3B01;\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n我必须使用NOEXPAND提示才能让它使用视图。
您会注意到计划中的警告是由于扫描整个表以查找这些值的事实,因为没有索引键控FirstNameHash。
不幸的是,尝试对此持久值创建非聚集索引失败:
\n\nCREATE NONCLUSTERED INDEX IX_FirstNameHash \nON dbo.PersonWithHashForSomeReason (FirstNameHash);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n消息 1976,级别 16,状态 1,第 48 行
\n
\n 无法在视图“dbo.PersonWithHashForSomeReason”上创建索引或统计信息“IX_FirstNameHash”,因为无法验证键列“FirstNameHash”是否精确且确定。考虑从索引或统计键中删除列,将列标记为保留在基表中(如果已计算),或者在键中使用非 CLR 派生列。
这是因为 SQL Server不信任我们:
\n\n\n\n\n为什么我们不信任\xe2\x80\x99 这个用户?这里真的会出什么问题吗?
\n\n假设用户对于非确定性函数错误地将自定义属性 IsDeterminsitic 设置为 true,并假设他能够在调用此函数的计算列上创建索引而不保留该索引。[...]这可能会导致索引损坏 ,因为该函数可能会为相同的输入返回不同的值,因为该函数是不确定的。
\n\n因此,为了用户\xe2\x80\x99的安全,此版本中的Sql Server要求用户保留计算列(与tsql情况不同)\n以实际索引计算列。
\n
我想全文索引也存在同样的限制,尽管我还没有尝试过。
\n\n正如您在自己的帖子中提到的,所有这一切的结果是您被困在这里。实际上你唯一的选择是:
\n\n| 归档时间: |
|
| 查看次数: |
366 次 |
| 最近记录: |