2008-08-15 28 views
6

私は、文字列に対して検索をしていたクエリがあります。今データベースの大文字と小文字を区別しないインデックス?

SELECT county FROM city WHERE UPPER(name) = 'SAN FRANCISCO'; 

を、これは正常に動作しますが、それはうまくスケールしない、と私はそれを最適化する必要があります。私はfound an optionのような生成されたビューを作成する行に沿っていますが、私はインデックスを使ったより簡単な解決策を望んでいました。

私たちはDB2を使用していますが、実際にはexpression in an indexを使用しますが、このオプションはz/OSでのみ使用できるように見えますが、Linuxを実行しています。とにかく表現インデックスを試してみました。

CREATE INDEX city_upper_name_idx 
ON city UPPER(name) ALLOW REVERSE SCANS; 

もちろん、UPPER(名前)はチョークします。

このような方法でインデックスなどを作成する別の方法はありますか。既存のクエリを再構築して新しい生成されたビューを使用したり、既存の列を変更したり、 ?

編集:私は他のデータベースのためのソリューションを聞くまで開いている...それはDB2に持ち越さかもしれません...

答えて

6

あなたは都市名の数値ハッシュキーを保持しているインデックス付きの列を追加することができます。 (重複を許して)。あなたのデシベルマニュアルを経由して、テーブルのインデックスを作成するためのオプションを見て、また

hash = [compute hash key for 'SAN FRANCISCO'] 

SELECT county 
FROM city 
WHERE cityHash = hash 
    AND UPPER(name) = 'SAN FRANCISCO' ; 

その後、マルチ句を行うことができます。何か役に立つかもしれない。

1

Oracleはファンクション索引をサポートしています。彼らの標準的な例:

create index emp_upper_idx on emp(upper(ename)); 
+1

残念ながら、DB2/LUWにはそれがまだありませんが、おそらくDB2/zにはそれがあるから来ているでしょう。 – paxdiablo

1

PostgreSQLは、関数の結果をインデックスサポートしています。私は考えることができる

CREATE INDEX mytable_lower_col1_idx ON mytable (lower(col1)); 

唯一の他のオプションは、に別の列を作成することによって、あなたのデータを非正規化ビットであり(トリガーによって更新された)大文字のバージョンを保持し、そのインデックスを作成します。ブリーチ!

+0

トリガーなどを必要とせず、DB2は生成された列をサポートします。 – paxdiablo

1

これはDB2で動作するかどうかわかりませんが、SQL Serverでこれをどのように行うか教えてください。 I MSSQLの処理方法はANSI標準ですが、特定の照合文字列は異なる場合があります。とにかく、アプリケーションの残りの部分を破棄せずにこれを行うことができれば、「名前」列で大文字と小文字を区別する必要がある場所は他にありますか? - 照合を変更してその列全体を大文字小文字を区別しないようにしてから、列にインデックスを付けます。

ALTER TABLE city ALTER COLUMN name nvarchar(200) 
    COLLATE SQL_Latin1_General_CP1_CI_AS 

...ここで、「nvarchar(200)」は、現在の列のデータ型を表します。照合文字列の "CI"部分は、MSSQLで大文字小文字を区別しないものとしてマークするものです。

説明する...私の理解では、インデックスはインデックス付き列の照合の順序で値を格納します。列の照合順序を大文字と小文字を区別しないようにすると、索引ストアは「サンフランシスコ」、「サンフランシスコ」、および「サンフランシスコ」となります。次に、問合せから「UPPER()」を削除するだけで、DB2は索引を使用できることを認識する必要があります。

また、これはSQL Serverについて私が知っていることだけに基づいており、数分でSQL-92仕様を見ています。 DB2の場合は動作する場合と動作しない場合があります。

1

DB2は照合に関して強くありません。また、関数ベースのインデックスはありません。

Niek Sandersの提案は、あなたのアプリケーションでハッシュが発生する必要がある場合(DB2がSHAまたはMD5関数を持っていない限り、私が知る限り)機能します。

しかし、私の場合は、CREATE TABLE ASを使用してマテリアライズド・ビュー(MQT ==マテリアライズ照会表)を作成し、事前計算された名前の大文字と小文字を事前に計算した列を追加します。注:DB2のマテリアライズド・ビューに索引を追加できます。

+1

他のテーブル全体を持つのではなく、既存のテーブルに別の生成されたカラムを追加するだけで、ストレージと速度の両方が安いです。そして、私はDB2が照合に弱いと訴えています。そして、あなたの妹のugl ...申し訳ありませんが、逃げました:-)。 – paxdiablo

5

短い回答、いいえ。

メインフレームで実行している場合は長い回答ですが、そうでない場合は他のトリッキーを使用する必要があります。

DB2(DB2/LUWのV8のような)ことができますので、今すぐ列を生成しました:

CREATE TABLE tbl (
    lname VARCHAR(20), 
    fname VARCHAR(20), 
    ulname VARCHAR(20) GENERATED ALWAYS AS UPPER(lname) 
); 

、その後ulnameにインデックスを作成します。私はあなたがそれを簡単にするつもりはないと思います。

これまでは、ulname列が同期していることを保証するために、挿入トリガーと更新トリガーの組み合わせを使用する必要がありましたが、これは維持するのが難しい問題でした。また、この機能はコアDBMSの一部であるため、高度に最適化されており(トリガベースのソリューションよりもはるかに高速です)、実際のユーザトリガの邪魔にならないため、維持する余分なDBオブジェクトはありません。

詳細はhereを参照してください。

関連する問題