Rac*_*ael -4 indexing search integer catalog sql-server-2008
有什么我想念的吗?
我想要创建的基本上是由空格(或您想要的任何类型)分隔的索引表.我意识到仅仅在int类型数据列上不可能进行全文搜索,因为它将"空格"理解为要在整个目录中编制索引的分隔数据的分隔符.
我确实意识到它确实允许我索引varbinary类型数据,但为什么不仅仅是int用空格分隔的数据,而不是包括要搜索的整数AND文本数据.IE,a
SEARCH * FROM MyTable
WHERE CONTAINS(indexedcolumn, '1189')
Run Code Online (Sandbox Code Playgroud)
使用为表格定义的全文索引/目录,如下所示:
indexedColumn secondDelimitedIntColumn
1189 34 34209 1989 3 5
Run Code Online (Sandbox Code Playgroud)
是不可能的,但是
SEARCH * FROM MyTable
WHERE CONTAINS(uniqueColumn, 'a1189')
Run Code Online (Sandbox Code Playgroud)
WOULD使用包含以下列的表格上的全文索引:
uniqueColumn secondDelimitedIntColumn
a1189 b34 b34209 b1989 b3 b5
Run Code Online (Sandbox Code Playgroud)
所以基本上CONTAINS()在任何具有全文索引的列上执行搜索只有在整数字符串附加了一些文本时才会起作用.
但我的问题是"为什么我不能只使用由空格分隔的整数字符串,这为我节省了必须添加虚拟文本的步骤,以便让SQL Server允许我对索引的整数字符串执行全文搜索?"
提前致谢!
这不是一个真正的问题.没有关于您尝试运行的查询或运行它的架构的详细信息.我不太确定在这里告诉你什么.如果有一些细节,我可能会帮助你.这更像是投诉而不是问题.
我完全知道这应该在评论部分而不是回答,但我没有关于溢出的要点.我住在.dba.
更新了XML示例,如下所示
您当前的设计违反了第1范式.
这本身就没问题.几年来,我继承并且必须维护几个这样做的系统.我不知道为什么他们这样建造.这并不重要.必须对它们进行维护,并且时间表并不总是如此,以至于有时间进行重构,测试和验证,更不用说为构建在它们上的应用程序堆栈这样做了.
不过现在回想起来,我可以很容易地发现他们共享的一个属性.这是优化和扩展这些系统的绝对最大障碍:基础"关系"数据库违反了第一范式.几乎每一个技术"疑难杂症"遇到过,几乎每一个性能问题,它的根本原因.拆分字符串.创建一个虚拟数据类型系统来验证它们.创建进一步的分隔属性来描述它们.为每个分隔的"位置"创建特殊规则,并且必须在许多系统中实现EVAL功能以强制执行它们.使用动态SQL或更糟糕的搜索它.花了更多"聪明"的编程来实现看起来像概念简单的功能而不是我想要回忆的东西.
也许你的系统不同.也许40多年的关系数据库研究并不适用于您的情况.为了你的缘故,我真的希望如此.唯一的问题是您以非关系方式使用关系数据库.就像你可以用锤子敲打螺丝一样,你可以用摩托车拉一条船(如果真的开始它就不要刹车),你可以在文字上创建一个索引(全文或b树)代表整数.
但你为什么要做这些事呢?为什么不将整数存储为整数并享受类型安全?为什么不将这个规范化为两个相关的表来利用较小的事务和更多的索引选项?如果你继承了一个你无法改变的系统,那么请说出来,人们可以帮助提供替代方案(TVP和XML被正确地提到).但是我看不到这种情况说你的锤子和摩托车坏了,因为它们不能很好地驱动螺丝和拉船.
所有这些(也许有人,某个地方正在重新思考一个不明智的设计),我LIKE在搜索分隔字符串时很好用:
-- Setup demo data
declare @delimitedInts table (
data varchar(max) not null
)
insert into @delimitedInts select '0,1,2'
insert into @delimitedInts select '1,2,3,4'
insert into @delimitedInts select '5,10'
-- Create a search term
declare @searchTerm int = 2
-- Get all rows that contain the searchTerm
select data
from @delimitedInts
where ',' + data + ',' like '%,' + cast(@searchTerm as varchar(11)) + ',%'
-- Create many search terms
declare @searchTerms table (
searchTerm int not null primary key
)
insert into @searchTerms select 2
insert into @searchTerms select 3
insert into @searchTerms select 4
-- Get all rows that contain ANY of the searchTerms
select distinct a.data
from @delimitedInts a
join @searchTerms b on ',' + a.data + ',' like '%,' + cast(b.searchTerm as varchar(11)) + ',%'
-- Get all rows that contain ALL of the searchTerms
select a.data
from @delimitedInts a
join @searchTerms b on ',' + a.data + ',' like '%,' + cast(b.searchTerm as varchar(11)) + ',%'
group by a.data
having count(*) = (select count(*) from @searchTerms)
Run Code Online (Sandbox Code Playgroud)
这对你来说太慢了吗?也许.你真的测过了吗?至少你可以得到一个实现,并在优化它之前证明它是有效的.
更新:XML
我已经做了一些测试,将您的以空格分隔的列转换为XML列并查询它,包括使用XML索引执行此操作.不幸的是,您无法在计算列上放置XML索引,因此我使用触发器来自动更新XML列.以下是一些有趣的结果(请注意SQL注释):
-- Create a demo table
create table MyTable (
ID int not null primary key identity
, SpaceSeparatedInts varchar(max) not null
--, ComputedIntsXml as cast('<ints><i>' + replace(SpaceSeparatedInts, ' ', '</i><i>') + '</i></ints>' as xml) persisted -- Can't use XML index
, IntsXml xml null
)
go
-- Create trigger to update IntsXml
create trigger MyTable_Trigger on MyTable after insert, update as begin
update m
set m.IntsXml = cast('<ints><i>' + replace(m.SpaceSeparatedInts, ' ', '</i><i>') + '</i></ints>' as xml)
from MyTable m
join inserted i on m.ID = i.ID
end
go
-- Add some demo data
insert into MyTable (SpaceSeparatedInts) select '1'
insert into MyTable (SpaceSeparatedInts) select '1 2'
insert into MyTable (SpaceSeparatedInts) select '2 3 4'
insert into MyTable (SpaceSeparatedInts) select '5 6 7 10'
insert into MyTable (SpaceSeparatedInts) select '100 10 1000'
go
-- Search for the number 10 (and use this same query in subsequent testing, below)
select *
from MyTable
where IntsXml.exist('/ints/i[. = "10"]') = 1
-- This query spends virtually all of its time running an XML Reader and an XPath filter
-- Add a primary xml index
create primary xml index IX_MyTable_IntsXml on MyTable (IntsXml)
-- The query now uses a clustered index scan and clustered index seek on PrimaryXML
-- Add secondary xml index for value
create xml index IX_MyTable_IntsXml_Value on MyTable (IntsXml) using xml index IX_MyTable_IntsXml for value
-- No change
-- Add secondary xml index for path
create xml index IX_MyTable_IntsXml_Path on MyTable (IntsXml) using xml index IX_MyTable_IntsXml for path
-- No change
-- Add secondary xml index for property
create xml index IX_MyTable_IntsXml_Property on MyTable (IntsXml) using xml index IX_MyTable_IntsXml for property
-- The query now replaces the clustered index scan on PrimaryXML with an index seek on SecondaryXML
Run Code Online (Sandbox Code Playgroud)
虽然它显然是一种不同的方法,但这比LIKE更快吗?你必须在你的环境中进行测试.希望这会给你一些如何做的想法.如果您的商店可以使用,请告诉我这对您有何影响.