4

私がしていること

複合型オブジェクトのバックエンド ストレージ メカニズムを提供する SQL テーブルを作成しています。最高のパフォーマンスでこれを達成する方法を決定しようとしています。複合型の個々の単純型値 (たとえば、Address 複合型の City の String 値) に対してクエリを実行できる必要があります。

複合型の値を XML として 1 つのレコードに格納できると当初は考えていましたが、この設計の検索パフォーマンスが気になります。 データベース アクセス層について何も変更せずに、その場で可変スキーマを作成できる必要があります


今いる場所

現在、以下の表を作成しようと考えています。

 TABLE:  Schemas
   COLUMN NAME       DATA TYPE
   SchemaId          uniqueidentifier
   Xsd               xml                 //contains the schema for the document of the given complex type
   DeserializeType   varchar(200)        //The Full Type name of the C# class to which the document deserializes.

 TABLE:  Documents
   COLUMN NAME       DATA TYPE      
   DocumentId        uniqueidentifier
   SchemaId          uniqueidentifier

 TABLE:  Values                            //The DocumentId+ValueXPath function as a PK
   COLUMN NAME       DATA TYPE      
   DocumentId        uniqueidentifier
   ValueXPath        varchar(250)
   Value             text

これらのテーブルから、クエリを実行するときに、値テーブルで一連の自己結合を行います。DocumentId でオブジェクト全体を取得したい場合は、複合型の非正規化されたデータ テーブルを模倣するビューを作成するための汎用スクリプトが必要です。


知りたいこと

私がしようとしていることを達成するためのより良い方法があると信じていますが、さまざまな SQL 手法の相対的なパフォーマンス上の利点については、私は少し無知です。具体的には、次のパフォーマンス コストがわかりません。

1 - comparing the value of a text field versus of a varchar field.
2 - different kind of joins versus nested queries
3 - getting a view versus an xml document from the sql db
4 - doing some other things that I don't even know I don't know would be affecting my query but, I am experienced enough to know exist

SQL のこれらのパフォーマンスの問題に関する情報やリソース、およびこの一般的な問題に効率的に取り組む方法についての推奨事項をいただければ幸いです。


例えば、

これは私が現在やろうとしていることの例です。

次のようなC#クラスのアドレスがあります

public class Address{
     string Line1 {get;set;}
     string Line2 {get;set;}
     string City {get;set;}
     string State {get;set;}
     string Zip {get;set;
}

インスタンスはから構築されますnew Address{Line1="17 Mulberry Street", Line2="Apt C", City="New York", State="NY", Zip="10001"}

その XML 値は次のようになります。

<Address>
   <Line1>17 Mulberry Street</Line1>
   <Line2>Apt C</Line2>
   <City>New York</City>
   <State>NY</State>
   <Zip>10001</Zip>
</Address>

上記の db-schema を使用すると、アドレス xml スキーマの XSD 定義を持つ Schemas テーブルに単一のレコードが作成されます。このインスタンスには、Schemas テーブルの Address レコードの SchemaId に割り当てられた uniqueidentifier (Documents テーブルの PK) があります。Values テーブルには、この Address を表す 5 つのレコードがあります。

それらは次のようになります。

DocumentId                              ValueXPath        Value
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Line1    17 Mulberry Street
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Line2    Apt C
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/City     New York
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/State    NY
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Zip      10001

バウンティが追加されました...

私の目的は、完全に検索可能で、アプリケーション層から生成されたデータ スキーマを持つデータ アクセス層をアプリケーションに与えるために必要なリソースを取得することです。新しい集約ルートをドメイン モデルに追加します。

私は、SQL 以外の .NET 互換テクノロジを使用する可能性を受け入れますが、そのような提案が検討されるためには、十分に実証されている必要があります。

4

5 に答える 5

3

アーキテクチャ レベルで解決策を探してみてはどうでしょうか。また、 CQRSを発見するまで、複雑なグラフとパフォーマンスに頭を悩ませていました。

【エバンジェリストモード開始】

  • ストレージとして、ドキュメントベースまたはリレーショナルに移行できます。両方でも!(イベントソーシング)
  • 関心の適切な分離: モデルの読み取りとモデルの書き込み
  • あなたのケーキを持って、それも食べてください!

わかりました、乗り越えるための最初の学習/技術曲線があります;)

【エバンジェリストモード終了】

あなたが述べたように、「データベースアクセスレイヤーについて何も変更せずに、その場で変数スキーマを作成できる必要があります。」主な利点は、読み取り用に作成されているため、読み取りモデルが非常に高速になることです。イベントソーシングをミックスに追加すると、読み取りモデルをドロップして、必要なスキーマに再構築できます...「オンライン」であっても。

多くの時間と技術的な課題を節約する nServiceBus のような優れたオープンソース フレームワークがいくつかあります。すべては、これらの概念をどこまで取り入れたいか、または時間をかけたいかによって異なります。Greg Young のアプローチに従えば、基本的なことから始めることもできます。以下のリンクの情報を参照してください。

見る

于 2011-03-11T10:43:30.423 に答える
2

どういうわけか、あなたが望むことは、SQL で行うのは面倒なことのように思えます。基本的に、SQL データベースにクエリを実行する場合と同様に、テキスト フィールドの内部は不透明として扱う必要があります。テキスト フィールドは、効率的なクエリ用に作成されていません。

シリアル化されたオブジェクトをテキスト フィールドに格納するだけであれば、それで問題ありません。ただし、テキスト フィールド内を参照してオブジェクトを検索するクエリを作成しようとしないでください。

あなたのアイデアは、何らかの結合、XML 解析、および XPath アプリケーションを実行して値を取得したいように思えます。これが最も効率的なことだとは思えません。

だから、私のアドバイス:

  • シリアル化されたオブジェクトをデータベースに保存するだけで、それらをロードして他のすべての操作をメモリ内で実行するだけです
  • または、複雑なデータ構造にクエリを実行する必要がある場合は、CouchDBMongoDBなどのドキュメント ストア/データベースを調査する必要があります。件名のウィキペディアを確認することもできます。個人的にはあまり好きではありませんが、特に XML を格納するように設計されたデータベースもあります。

補遺、上記の説明によると

簡単に言えば、このことでやり過ぎないでください。

  • C#/.NET オブジェクトを永続化するだけの場合は、フレームワークに既に組み込まれている XML シリアライゼーションを使用するだけで、単一のテーブルで完了します。
  • 何らかの理由で複雑な XML を保存する必要がある場合は、専用の XML ストアを使用してください
  • データベース スキーマが固定されているが、複雑すぎて効率的なクエリを実行できない場合は、クエリを高速化するためにデータの非正規化バージョンを保持するメモリ内のドキュメント ストアを使用します (または単にデータベース スキーマを単純化します)。
  • 固定スキーマが本当に必要ない場合は、ドキュメント ストアのみを使用し、「スキーマ定義」を一切忘れてください。

あなたの解決策については、はい、何とか機能する可能性があります。正しく設定すれば、プレーンな SQL スキーマも同様です。しかし、XPath を適用する場合、おそらくレコードにアクセスするたびに XML ドキュメント全体を解析することになるため、最初からあまり効率的ではありません。

Document データベースを調べたい場合は、CouchDBおよびMongoDB用の .NET ドライバーがあります。eXist XML データベースは多数のWeb プロトコルを提供しており、おそらく VisualStudio のポイント アンド シュート インターフェイスを使用してクライアント クラスを簡単に作成できます。または、すでに行った人をグーグルで検索してください。

于 2011-02-23T14:34:30.950 に答える
1

データベース アクセス層について何も変更せずに、その場で可変スキーマを作成できる必要があります。

RDBMS 内で RDBMS を再実装しています。DBはすでにこれを行うことができます-それはDDLステートメントが好きcreate tableであり、そのcreate schemaためのものです....

「スキーマ」とSQLセキュリティを調べることをお勧めします。適切なセキュリティ設定があれば、ユーザーが独自のテーブルを作成してドキュメント属性を保存したり、自動的に生成したりすることを許可できない理由はありません。

編集: 少し長い回答です。すぐに完全な要件がない場合は、データを XML データ型として保存し、XPath クエリを使用してクエリを実行します。これは、少数の行 (確かに数千未満) に対する不定期のクエリには問題ありません。

また、RDBMS が XML を介したインデックスをサポートしている場合もあります。これは、問題を解決する別の方法である可能性があります。CREATE XML INDEXたとえば、SqlServer 2008 では。

ただし、クエリが頻繁に発生する場合は、トリガーまたは具体化されたビューを使用して関連データのコピーをテーブル形式で作成できるため、ブレークアウト テーブルをクエリすることで、より集中的なレポートを高速化できます。

あなたの要件はわかりませんが、レポート/クエリを自分で作成する責任がある場合は、これを使用する方法があります。ユーザーが独自のレポートを作成できるようにする必要がある場合、これはより大きな山を登る必要があります。

私が言っているのは、「これを行う必要があり、XML だけではその仕事ができないということですか」ということだと思います。

于 2011-03-10T18:15:06.007 に答える
0

興味深い質問です。

ここで間違った質問をしているのではないかと思います。大まかに言えば、テキストフィールドにFULLTEXTインデックスがある限り、クエリは高速になります。たとえば、ワイルドカードを使用する必要がある場合は、varcharよりもはるかに高速です。

ただし、私があなたである場合は、実行する実際のクエリに集中します。ブール演算子が必要ですか?ワイルドカード?数値比較?ここで、実際のパフォーマンスの問題に遭遇すると思います。

次のようなクエリが必要になると思います。

  • 「ニューヨーク州、ニュージャージー州、ペンシルベニア州のすべての住所を検索する」
  • 「マルベリーストリートの家番号1から100までのすべての住所を検索してください」
  • 「郵便番号が欠落しているすべての住所を検索し、都市はニューヨークです」

大まかに言うと、提案するソリューションは、XMLをどこかに格納してから、そのXMLを名前と値のペアに非正規化してクエリを実行することです。

名前と値のペアには長く誇り高い歴史がありますが、リレーショナルデータベースモデルの組み込みの最適化と概念を使用していないため、複雑なクエリの状況では扱いにくくなります。

私がお勧めするいくつかの改良点は、ドメインモデルを調べて、少なくとも個別のデータ型を「値」列に除外できるかどうかを確認することです。最終的には「textValue」、「moneyValue」、「integerValue」、「dateValue」になる可能性があります。あなたが与える例では、「住所1」を「housenumber」(整数として)と「streetname」に因数分解するかもしれません。

とはいえ、ドキュメントに焦点を当てたデータベースに完全に変更する以外に、これ以上の解決策はないと思います。

于 2011-03-09T11:36:32.667 に答える
0

一部は、DB エンジンに依存します。SQL Server を使用していますね。

トピックへの回答:

1 - text フィールドと varchar フィールドの値を比較する: 2 つの db フィールドを比較する場合、varchar フィールドの方が賢明です。Nvarchar(max) は、データを 2*l+2 バイトの Unicode で格納します。ここで、"l" は長さです。パフォーマンスの問題については、テーブル フィールドにインデックスを付ける (またはしない) 最良の方法を選択するために、テーブルがどれだけ大きくなるかを考慮する必要があります。トピックを参照してください

2 - ネストされたクエリを簡単に作成して実行できる場合があり、クエリ時間を短縮する方法としても機能します。ただし、複雑さによっては、異なる種類の結合を使用する方がよいでしょう。最良の方法は、両方の方法で行うことです。DBエンジンは最初の実行時にクエリを「コンパイル」するため、各クエリを2回以上実行し、その後の実行は非常に高速です。さまざまなパラメーターの時間を測定し、最適なオプションを選択します。

「場合によっては、サブクエリを書き直して JOIN を使用し、パフォーマンスを向上させることができます。JOIN を作成する利点は、クエリで定義された順序とは異なる順序でテーブルを評価できることです。サブクエリを使用する利点は、多くの場合、そうでないことです。サブクエリ式を評価するために、サブクエリからすべての行をスキャンする必要があります。-リンク

3-この質問にはあまり情報がありませんが、テーブルから直接xmlドキュメントを取得する場合は、ビューを挿入することをお勧めします. 繰り返しますが、それはビューとドキュメントに依存します。

4-その他の問題は、テーブルに予想される合計レコードに関するものです。ソート、結合、フィルタリング、PK および FK を考慮する必要がある列のインデックス作成。状況ごとに異なるアプローチが必要になる場合があります。私の提案は、データベースエンジンとクエリが機能し、システムに関連していることについて読むことに時間を費やすことです。

お役に立てば幸いです。

于 2011-02-23T15:18:32.800 に答える