0

私のデータベーステーブル(geo ip lookup)には7つの列があり、そのうち2つの列が<composite-id>を構成しています。ここで、最初の2つの列を使用して値を検索すると、レコードをフェッチするのに12〜14秒かかります。

私のDAOコードは次のようになります。

String queryString = "from Igeo igeo where igeo.ip_from <= " + ip
            + "and igeo.ip_to >= " + ip;

    Query q = session.createQuery(queryString);
    List<Igeo> igeoList = q.list();

    if(igeoList.size() > 0){
        Igeo igeo = igeoList.get(0);

        ISP = igeo.getIsp();
        ...
        ...         
    }

* Igeo=java表現テーブルのクラス

**レコードは、ipがcomposite-id列の値の間にある場合にフェッチされます。

ip_from = 1; ip_to = 3; ip = 2;

したがって、上の行が返されます

このテーブルはレコードの読み取りにのみ使用されます。上記よりも効率的なqueryStringを提案してください

4

2 に答える 2

4

最初に休止状態を削除し、クエリ ブラウザーでクエリを実行して、返されるまでの時間を確認します。同じ時間がかかる場合は、Hibernate ではありません。それはデータベースのパフォーマンスです。ip_from と ip_to の 2 つの列にインデックスを追加してください。また、クエリに対してクエリ プランを実行して、内部で実行されているデータベースを確認し、クエリ プランを試して最適化することもできます。

あなたのように、クエリに連結を使用しないことをお勧めします。これにより、外部からの潜在的な SQL インジェクションを可能にするセキュリティ ホールが生成されます。以下を使用することをお勧めします。

Query q = session.createQuery("from Igeo igeo where igeo.from_ip >= ? and igeo.to_ip <= ?");
q.setString( 0, ip );
q.setString( 1, ip );

名前付きパラメーターを使用して、もう少し短くすることもできます。

于 2012-07-24T14:47:09.293 に答える
0

テーブル IGeo に重複する ip_from と ip_to の範囲が含まれていない場合は、これを試してください。

    String queryString = "FROM Igeo igeo"
        +  " WHERE igeo.ip_to >= " + ip
        +  " ORDER BY igeo.ip_to";

次に、リストの最初の項目を確認します (ip_from <= ip であることを確認します)。

テーブルに重複する ip_from と ip_to の範囲が含まれていたとしても、上記の HQL の方が高速に実行されるに違いありません。

<余談>ですが、「ip」のような生の文字列を HQL や SQL に連結するべきではありません。SQL インジェクション攻撃の脆弱性につながります。代わりにクエリ パラメータを使用する</Aside>

また、データベースの Igeo.ip_to に対応する列にインデックスがあることを確認してください。

あなたの説明から、データベースには Igeo.ip_from + IGeo.ip_to の主キーがあるように思えます。ip_from と ip_to の値が重複していない場合、正規化されていないようです。主キーに必要な列は 1 つだけです。両方の列を主キーとして使用することを選択した場合、上記のクエリは単一のインデックスを追加することで利益を得ることができます。

ip_to および ip_from で始まる、テーブル内のすべての列を含むインデックスを追加すると、一部のデータベースのパフォーマンスが向上します。(これにより、データベースはインデックスのみにアクセスしてクエリを満たすことができます)。MySQL がこの程度まで最適化できるかどうかはわかりませんが、DB2 と Oracle がこれを提供してくれることはわかっています。

于 2012-07-24T14:57:40.333 に答える