2008-08-15 110 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

您可以添加一個索引列拿着城市名的數值哈希鍵。 (允許重複)。

那麼你可以做多where子句中:

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 2009-01-07 06:24:09

1

的PostgreSQL還支持索引功能結果:

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

我能想到的唯一的其他選擇是通過創建另一列到有點反規範化數據保持大寫版本(由觸發器更新)並將其編入索引。布萊什!

+0

不需要觸發器等,DB2支持生成的列。 – paxdiablo 2009-01-07 06:27:33

1

我不知道這是否可以在DB2中工作,但我會告訴你如何在SQL Server中執行此操作。我想認爲 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在整理方面並不強大。它沒有基於功能的索引。

如果您可以接受散列必須發生在您的應用程序中(因爲據我所知,DB2沒有SHA或MD5函數),Niek Sanders的建議將會起作用。但是,如果我是你,我會使用CREATE TABLE AS創建一個物化視圖(MQT ==物化查詢表,採用db2說法),添加一個預先計算的名稱大寫變體的列。注意:您可以在DB2中爲物化視圖添加索引。

+1

在存儲和速度方面更便宜,只需將另一個生成的列添加到現有表中,而不是使用其他表格。我認爲DB2在排序方面很薄弱。而且,你妹妹的醜陋......對不起,被偷走了:-)。 – paxdiablo 2009-01-07 06:26:46

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