3

DAL2 リポジトリのデフォルトの Get() 関数が結果を返すのに数秒かかるという問題があります。SQL Server Management Studio を使用してデータベースにレコードを直接クエリすると、クエリはすぐに返されます。この関数は基本的な関数で、次のようになります。

public MyThing Get(string primaryKey)
{
    MyThing myThing;
    using (IDataContext ctx = DataContext.Instance(“DATABASECONN”))
    {
        var rep = ctx.GetRepository<MyThing>();
        myThing = rep.GetById(primaryKey);
    }
    return myThing;
}

テーブルには 80 万以上のエントリがあります。

キャッシュ設定が有効になっていても、関数は後続の実行で同じ実行時間になります。

なぜこれはゆっくりと機能しているのですか?どうすればスピードアップできますか?

4

1 に答える 1

5

調査

コードのデバッグ中に、データベースで SQL プロファイラーを実行しました。GetById() 関数が初めて呼び出されたときに、データベース テーブルからすべてのレコードを選択するクエリが実行されることがわかりました。主キーはデータベースに渡されません。次に GetById() 関数が実行されるとき、データベースは照会されません。結果は、キャッシュされた値から返されます。

したがって、GetById() 関数から返される単一のレコードは、テーブル内のすべてのレコードの結果セットを検索した結果である必要があります。この関数がどのように動作し、レコードを取得するかの詳細は、コンパイルされたコードにあります (このコンパイルされたコードのソースはおそらく利用可能ですが、私はまだ調査していません)。

このコードの実行中のメモリ使用量を調べて、IIS に十分な量があることを確認しました。IIS の設定は、アプリケーション プールが利用可能なメモリを使用できるように設定されています。w3wp.exe プロセスのメモリ使用量のデバッグ中に、.75 ~ 1.3 GB の間で変動しました。必要に応じてサイトがさらに使用できるように、十分な追加 RAM が利用可能でした。

これらの実験のハイライトは次のとおりです。

  • GetById() 関数が初めてデータベース テーブルにヒットすると、テーブルからすべてのレコードが選択されます。
  • キャッシュは期待どおりに機能しているため、繰り返しクエリがデータベースにヒットしていません。
  • IIS で使用できるメモリの量に関係なく、キャッシュから結果を取得するには数秒かかります。

ソリューション

この問題を解決するために、アプローチを変更しました。SELECT 中に主キーを使用してデータベースに直接クエリを実行すると、クエリはすぐに返されました。これにより、DAL2 リポジトリの Find() 関数を使用して、SELECT の条件を自分で指定できるようになりました。
私が作成した関数は次のようになります。

public MyThing Get(string primaryKey)
{
    MyThing myThing = (MyThing)DataCache.GetCache(primaryKey);
    if (myThing != null)   
        return myThing;

    IList<MyThing> myThings;
    using (IDataContext ctx = DataContext.Instance(“DATABASECONN”))
    {
        var rep = ctx.GetRepository<MyThing>();
        myThings = (IList<MyThing>)rep.Find("WHERE myPrimaryKeyFieldName = @0", primaryKey);
        if (myThings.Count > 0)
            DataCache.SetCache(primaryKey, myThings[0]);
    }
    return myThings.Count > 0 ? myThings[0] : null;
}

上記の関数は Find() 関数を使用しているため、DAL2 ではキャッシュが実装されていません。これを支援するために、カスタム キャッシング技術を組み込みました。SQL プロファイラーを使用してこの関数を調査したところ、同じ primaryKey 値を使用して関数を繰り返し呼び出してもデータベースにヒットしなかったため、キャッシュが期待どおりに動作していたことがわかりました。

この方法で使用されるキャッシュは、GetById() を使用する場合のように実行時間を遅くしません。タイマーとして使用される関数内に配置された DateTime は、次の実行時間を示します。データベースがヒットしたときは、00:00:00.1 以下。キャッシュにヒットしたとき、実行時間は 0 でした。これは大規模なテストではありませんでしたが、私が実行したテストでは実行時間は一貫していました。

結論

上記のテストと解決策は、DAL2 の GetById() を注意して使用する必要があることを示しています。データベースのサイズによっては、レコードを取得することが必ずしも最善の解決策とは限りません。データ取得の実行速度が遅い場合は、ソリューションで提案されている方法などの代替方法を検討してください。

GetById() が最適なソリューションではなくなったテーブル内のレコードの正確な数を把握することは役に立ちます。この数は、オブジェクト内のデータのサイズによって異なる可能性があります。おそらく計算可能ですが、現時点では方程式がないため、ケースバイケースで計算する必要があります。

他の誰かがこのトピックに関する追加情報を持っている場合は、ディスカッションに追加してください。

于 2013-11-15T22:13:26.570 に答える