3

Fluent-NHibernate (自動マッピング付き) を使用してテーブルを生成していますが、デフォルトで使用される ID フィールドとは異なるクラスター化インデックスを選択したいと考えています。Fluent NHibernate を使用して、デフォルトの主キー フィールド以外のフィールドにクラスター化インデックスを作成するにはどうすればよいですか?

この背後にある主な理由は単純です。主キー フィールドに Guid を使用しています。デフォルトでは、NHibernate は主キー フィールドにクラスター化インデックスを作成します。通常、Guid は連続していないため、主キー フィールドでクラスタリングを行うとパフォーマンスの問題が発生します。

ご存知のように、テーブルの最後にレコードを追加する方が、テーブル内にレコードを挿入するよりもはるかに安価な操作です。また、テーブル内のレコードは、クラスター化インデックス内のアイテムの順序で物理的に格納されます。Guid はいくぶん「ランダム」であり、シーケンシャルではないため、テーブルに既に存在する他の Id Guid の値よりも小さい新しい Guid が生成される場合があります。その結果、追加ではなくテーブルの挿入が行われます。

これを最小限に抑えるために、DateTime 型の CreatedOn という列があります。すべての新しいレコードが挿入されるのではなく追加されるように、この CreatedOn 列でテーブルをクラスター化する必要があります。

これを達成する方法についてのアイデアは大歓迎です!!!

注: Sequential Guid を使用できることはわかっていますが、セキュリティ上の理由から、そのパスをたどりたくありません。


注: この投稿に対する回答はまだありませんが、現時点で考えているアイデアがいくつかあります。

  1. Fluent なしで NHibernate を使用すると、クラスター化されたインデックスを NHibernate で直接作成できる可能性があると思います。これを行う方法を知るには、NHibernate についてまだ十分に知りません。私はかなり(ほぼ絶対に)それができると確信しています。

  2. Fluent-NHibernate には、最近の書き直しの前に、SQL オブジェクトに属性 (クラスター化インデックスなど) を設定する方法が含まれていました。現在、そのオプションはなくなっているようです。そのオプションがまだ利用可能かどうかを確認するために、おそらくどこかに質問を投稿します。もしそうなら、おそらくそれを使用してクラスター化インデックスを設定できます。

  3. Fluent-NHibernate は、構成が流暢に構築されたら、手動編集用に構成を公開する機能を提供します。この機能を試したことはありませんが、クラスター化インデックスを設定するために必要なレベルの粒度が提供される可能性があると期待しています。

  4. 最悪のシナリオでは、生成されたすべてのテーブルのクラスター化インデックスを変更する SQL スクリプトを作成できます。ただし、このアプローチに関していくつか質問があります。A. 自動スキーマ生成を使用しているため、NHibernate は次に構成を評価するときにクラスター化インデックスの変更を「元に戻す」ことはできますか? 2. クラスタ化インデックスが変更されたことを検出した場合、NHibernate はエラーになりますか? これをテストする必要がありますが、まだ行っていません。しかし、私はこのソリューションが本当に嫌いです。SQLServer2008 および MySQL に対して DB をテストしています。NHibernate の優れた点の 1 つは、データベースに依存しないことです。スクリプトを導入すると、すべての賭けがオフになります。

  5. このインターフェイスから継承する IPropertyInstance クラスには、フィールドにインデックスを作成できるようにする Index プロパティがあります。問題は、クラスター化されたインデックスを作成できるようにするフラグやその他のオプションがないことです。最も簡単な解決策は、このメソッドにプロパティを追加して、クラスター化インデックスを作成できるようにすることです。これを Fluent-NHibernate 開発者に提案できると思います。

4

4 に答える 4

7

これは古い投稿ですが、他の人の助けになれば幸いです。これは、MS SQL Server での私の経験から来ています。プラットフォームが異なれば必要なソリューションも異なると思いますが、これは良い出発点になるはずです。

NHibernate は主キーに CLUSTERED インデックスを設定しません。これは、SQL Server の既定の動作です。テーブルごとに 1 つの CLUSTERED しか存在できないため、最初に主キーでの CLUSTERED の作成を回避する必要があります。

これを達成する唯一の方法は、カスタム Dialect を作成して、適切な PrimaryKeyString をオーバーライドすることです。NHibernate のデフォルトはDialect.csから取得されます。

    public virtual string PrimaryKeyString
    {
        get { return "primary key"; }
    }

SQL サーバーの場合

    public override string PrimaryKeyString
    {
        get { return "primary key nonclustered"; }
    }

これにより、SQL Server は NONCLUSTERED プライマリ キーを強制的に作成します。XML マッピング ファイルのタグを使用して、お気に入りの列に独自の CLUSTERED インデックスを追加できるようになりました。

<database-object>
  <create>
    create clustered index IX_CustomClusteredIndexName on TableName (ColumnName ASC)
  </create>
  <drop>
    drop index IX_CustomClusteredIndexName ON TableName
  </drop>
</database-object>
于 2011-01-14T13:52:47.083 に答える
1

あなた自身が言ったように、別のオプションは guid.comb ID 生成戦略に切り替えることです。この場合、PK uid は Guid である部分と、生成された ID が連続していることを保証する部分に基づいています。

Jeffrey Palermo の投稿で詳細情報を確認してください

しかし、セキュリティ上の理由からそれを行いたくないとおっしゃっていますが、それはなぜですか?

于 2009-09-01T05:16:52.743 に答える
1

具体的にお答えすることはできませんが、ここにいるのでデータベースの情報をお伝えします。

非クラスター化インデックスで主キーを作成するように NHibernate に指示する必要があります。テーブルごとにクラスター化インデックスしか存在できないため、テーブルをヒープとして作成し、クラスター化インデックスを配置する必要があります。

于 2009-08-31T09:01:28.357 に答える
0

@ abx78が言ったように、これは古い投稿ですが、この問題の解決策についても私の知識を共有したいと思います. アイデア 3「Fluent NHibernate がマッピングを公開する」のソリューションを構築しました。

configuration.ClassMappings構成が構築された後 (したがって、マッピングが解析されます)、Fluent NHibernate は、およびを使用して実際のマッピングを調べる機会を与えてくれますconfiguration.CollectionMappings。後者は、以下の例で使用され、Sql Server でクラスター化されたインデックスを生成する複合主キーを設定します (@abx78 が指摘するように)。

foreach (var collectionMapping in configuration.CollectionMappings) {
    // Fetch the columns (in this example: build the columns in a hacky way)
    const string columnFormat = "{0}_id";
    var leftColumn = new Column(string.Format(
        columnFormat,
        collectionMapping.Owner.MappedClass.Name));
    var rightColumn = new Column(string.Format(
        columnFormat,
        collectionMapping.GenericArguments[0].Name));
    // Fetch the actual table of the many-to-many collection
    var manyToManyTable = collectionMapping.CollectionTable;
    // Shorten the name just like NHibernate does
    var shortTableName = (manyToManyTable.Name.Length <= 8)
                                ? manyToManyTable.Name
                                : manyToManyTable.Name.Substring(0, 8);
    // Create the primary key and add the columns
    // >> This part could be changed to a UniqueKey or to an Index
    var primaryKey = new PrimaryKey {
        Name = string.Format("PK_{0}", shortTableName),
    };
    primaryKey.AddColumn(leftColumn);
    primaryKey.AddColumn(rightColumn);
    // Set the primary key to the junction table
    manyToManyTable.PrimaryKey = primaryKey;
    // <<
}

ソース: Fluent NHibernate: 多対多結合テーブルでクラスター化インデックスを作成する方法は?

于 2012-06-13T07:57:14.807 に答える