-5

足りないものはありますか?

私が作成しようとしているのは、基本的にスペースで区切られたインデックスのテーブルです (または任意のタイプ)。全文検索は、単に int 型のデータ列では不可能であることを認識しています。これは、「スペース」を、カタログ全体で索引付けされる分離されたデータの区切り文字として理解するためです。

タイプデータにインデックスを付けることができることは理解していますが、検索する整数とテキストデータを含めるのではなく、スペースで区切られたデータvarbinaryだけではないのはなぜですか。intIE、

 SEARCH * FROM MyTable
 WHERE CONTAINS(indexedcolumn, '1189')

次のようなテーブルに対して定義されたフルテキスト インデックス/カタログを使用します。

 indexedColumn      secondDelimitedIntColumn
 1189               34 34209 1989 3 5

不可能ですが、

 SEARCH * FROM MyTable
 WHERE CONTAINS(uniqueColumn, 'a1189')

次の列を持つテーブルで全文索引を使用して機能します。

 uniqueColumn secondDelimitedIntColumn
 a1189        b34 b34209 b1989 b3 b5  

そのため、基本的にCONTAINS()、全文索引のある任意の列で検索を実行すると、整数文字列にテキストが添付されている場合にのみ機能します。

しかし、私の質問は、「スペースで区切られた整数の文字列を使用できないのはなぜですか。これにより、SQL Server をだましてインデックス付きの整数文字列で全文検索を実行できるようにするためだけにダミー テキストを追加する必要がなくなります。 ?」

前もって感謝します!

4

3 に答える 3

6

これは本当に質問ではありません。実行しようとしているクエリまたは実行しているスキーマに関する詳細はありません。ここで何を伝えたらいいのかよくわかりません。細かいところがあれば教えていただけると助かります。質問というより苦情のようなものです。

これはコメントセクションにあり、回答しない必要があることを十分に認識していますが、オーバーフローに関するポイントはありません。私は.dbaに住んでいます。

于 2012-10-18T20:55:38.780 に答える
5

以下のXMLの例で更新

現在のデザインは第一正規形に違反しています。

それ自体は大丈夫です。何年にもわたって、私は継承し、そうするいくつかのシステムを維持しなければなりませんでした。なぜそのように建てられたのかわかりません。それは本当に重要ではありません。それらを維持する必要があり、それらに基づいて構築されたアプリのスタックに対してそうすることは言うまでもなく、リファクタリング、テスト、および検証の時間があるようなスケジュールではありませんでした。

しかし、今振り返ると、彼ら全員が共有している1つの属性を簡単に見つけることができます。これは、これらのシステムを最適化および拡張する上での絶対的な最大の障壁でした。基盤となる「リレーショナル」データベースは、第一正規形に違反していました。事実上すべての技術的な「落とし穴」が発生し、事実上すべてのパフォーマンスの問題が根本的な原因でした。文字列を分割します。それらを検証するための偽のデータ型システムを作成します。それらを説明するためにさらに区切られた属性を作成します。区切られた「場所」ごとに特別なルールを作成し、それらを適用するために多くのシステムでEVAL関数を実装する必要があります。動的SQL以下を使用してすべてを検索します。概念的に単純な機能のように見えるものを実装するには、私が思い出すよりも多くの「巧妙な」プログラミングが必要でした。

たぶんあなたのシステムは違うでしょう。たぶん、40年以上のリレーショナルデータベースの研究はあなたの状況には当てはまりません。あなたのために、私は本当にそう願っています。唯一の問題は、リレーショナルデータベースを非リレーショナルな方法で使用していることです。ハンマーでネジを叩くことができ、オートバイでボートを引くことができるのと同じように(実際にそれを実行する場合はブレーキを踏まないでください)、テキストにインデックス(フルテキストまたはBツリー)を作成できますそれは整数を表します。

しかし、なぜあなたはこれらのことのいずれかをするのですか?実際に整数を整数として格納し、型安全性を楽しんでみませんか?これを2つの関連するテーブルに正規化して、より小さなトランザクションとより多くのインデックス作成オプションを利用しないのはなぜですか?変更できないシステムを継承している場合は、そのように言ってください。そうすれば、人々は代替案を手伝うことができるかもしれません(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)

これはあなたにとって遅すぎますか?多分。実際に測定しましたか?少なくとも、実装を導入して、最適化する前にそれが機能することを証明することができます。

更新: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

明らかに別の方法ですが、これはLIKEよりも高速ですか?環境でテストする必要があります。うまくいけば、これはあなたにそうする方法のいくつかのアイデアを与えるでしょう。それがあなたの店で実行可能であるならば、これがあなたのためにどのようにうまくいくかを私に知らせてください。

于 2012-10-18T21:43:30.083 に答える
1

あなたが探しているものを理解しているかどうかはわかりませんが、単一の列に複数の値を格納したい場合は、XML を使用することをお勧めします。

コンセプトの詳細については、この記事を参照してください。

SQLServer 2005 での XML 列のクエリ

于 2012-10-18T22:33:28.227 に答える