2016-09-01 4 views
1

私はストリート名のみを持っていて、ストリート名を含むデータベース内のすべてのアドレスを検索しようとしています。たとえば、私はMojave Rd、データベースの値は123 Mojave Rd Las Vegasです。これは私に先導的かつ終わりのワイルドカードを使用させる。私は何百ものストリート名に対して次のクエリを実行しようとしています。実行計画は良好に見えますが、クエリは常にタイムアウトします。この方法を最適化するには先頭にワイルドカードを使用するようにOracle

SELECT 
    full_address, 
    city, 
    state, 
    zip 
FROM 
    address_table 
WHERE 
    full_address LIKE '%MOJAVE RD%' 
AND 
    state IN ('NV'); 
+0

特に状態のインデックスが作成されている場合、何百もの問題はありません。説明の計画を投稿してください。 – vercelli

+2

「タイムアウト」とはどういう意味ですか?私は完了するのに数時間かかってしまい、決して「タイムアウト」しなかったクエリを実行しました。あなたのデータベースのパラメータをチェックしてください...私はあなたが文字列の先頭にワイルドカードを持つことによってインデックスが持つ可能性のある肯定的な効果を否定していると思います(afaikはさらにそれが右側にあるほど、中古)。 PS:正規化を使用して原子性を確立すると助けになる可能性があります。 – daZza

+0

ワイルドカードで始まるLIKEを使用すると、クエリオプティマイザはそのフィールドのインデックスを無視します。しかし長いvarcharsは索引付けされないことが多いので、LIKEを使用すると索引付けが遅くなることはありません。しかし、クエリは状態のインデックスから利益を得るだろう。 – LukStorms

答えて

1

Oracle Textはこれに適しています。

スーパー基本的な例:あなたはそれを使用することにした場合

CREATE INDEX test_idx_addr ON address_table (full_address) 
indextype is ctxsys.context; 

select * from address_table 
where contains(full_address,'MOJAVE RD') > 0; 

。しかしそれはたくさんありますが、非常によくそれをよく読んで。

0

私はOracle Textソリューションが最も好きです。一方:

通常の索引を使用して簡単な解決策を実行している場合は、カバー索引を試して、索引フルスキャンを実行するプランを強制することができます。 これは試行するための示唆にすぎず、すべての場合に適切な解決策ではありません。

まず、クエリが現在使用しているプラ​​ンを確認します。

たとえば、インデックスをちょうど(state, full_address)に設定してから、問合せの実行計画を確認します。次のようにして、テーブル全体のスキャンを実行します。新しい索引でフルスキャンを行い、続いてRowidによる表アクセスが行われると、その作業は完了です。

計画は自動的にインデックス(すなわち、それはまだFTSをやっている)をピックアップしていない場合、あなたはこのようなもので、その手を強制することができます:

SELECT 
    a.full_address, 
    a.city, 
    a.state, 
    a.zip 
FROM 
    address_table a 
WHERE a.rowid in (
    select a1.rowid from address_table a1 
    where a1.full_address LIKE '%MOJAVE RD%' 
    AND a1.state IN ('NV') 
); 

同じことを達成するための他の方法は、おそらくあります。効果。考えられるのは、一致する行の索引に対して可能な限り高速なスキャンを実行できるようにすることで、表から必要な残りのデータを取得することです。

NOTEしかし、この計画のパフォーマンスは非常によくあなたの現在の状況よりも悪いことができること - テーブル内のレコードを一致させる合理的に大音量がある場合は特に。

もちろん、statefull_addressのカラムだけを取得するように要件を変更することができれば、これはさらに高速になります(テーブルへのアクセスを完全に避けることができるため)。

関連する問題