2008-08-15 19 views
6

Mam kwerendy, gdzie szukam na sznurku:Niewrażliwy indeks bazy danych?

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

Teraz to działa prawidłowo, ale nie skaluje się dobrze, i muszę go zoptymalizować. Mam found an option wzdłuż linii tworzenia wygenerowanego widoku lub coś podobnego, ale miałem nadzieję na prostsze rozwiązanie przy użyciu indeksu.

Używamy DB2, i naprawdę chcę użyć expression in an index, ale opcja ta wydaje się być dostępna tylko w systemie z/OS, ale używamy systemu Linux. Mimo to spróbowałem indeksu wyrażenia:

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

Ale oczywiście dławi się NA GÓRZE (nazwa).

Czy istnieje inny sposób, w jaki mogę utworzyć indeks lub coś podobnego w ten sposób, że nie będę musiał zmieniać moich dotychczasowych zapytań, aby korzystać z nowego wygenerowanego widoku, ani zmieniać moich istniejących kolumn, ani żadnej innej takiej inwazyjnej zmiany? ?

EDIT: Jestem otwarty na kontakt rozwiązania dla innych baz danych ... to może przenieść do DB2 ...

Odpowiedz

6

Można dodać indeksowanej kolumny gospodarstwa numeryczną klawisza skrótu nazwy miasta. (Dozwolone duplikaty).

Następnie można zrobić multi-klauzulę gdzie:

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

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

Ewentualnie przejść przez instrukcji db i spojrzeć na możliwości tworzenia indeksów tabeli. Może być coś pomocnego.

1

Oracle obsługuje indeksy oparte na funkcjach. Ich kanoniczny przykład:

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

Niestety, DB2/LUW tego jeszcze nie ma, ale prawdopodobnie nadchodzi od czasu, gdy DB2/z go posiada. – paxdiablo

1

PostgreSQL obsługuje również indeksowanie wyników funkcję:

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

Jedynym rozwiązaniem można myślę, jest de-normalizacji danych nieco, tworząc kolejną kolumnę trzymaj wielką wersję (aktualizowaną przez wyzwalacze) i indeksuj ją. Blech!

+0

Nie wymagają wyzwalaczy i tym podobne, DB2 obsługuje wygenerowane kolumny. – paxdiablo

1

Nie wiem, czy to działałoby w DB2, ale powiem ci, jak to zrobić w SQL Server. I think sposób MSSQL to jest standard ANSI, choć specyficzne ciągi sortowania mogą się różnić. W każdym razie, jeśli możesz to zrobić bez niszczenia reszty aplikacji - czy są inne miejsca, w których w kolumnie "nazwa" musi być rozróżniana wielkość liter? - spróbuj zmienić wielkość sortowania w całej kolumnie bez kolumny, a następnie zindeksuj kolumnę.

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

... gdzie "nvarchar (200)" oznacza bieżący typ danych kolumny. Część "CI" ciągu sortowania określa to jako nieodczuwalną na wielkość liter w MSSQL.

Aby wyjaśnić ... rozumiem, że indeks będzie przechowywać wartości w porządku sortowania kolumny indeksowanej. Uzależnienie kolumny od wielkości liter sprawi, że indeks sklepu "San Francisco", "SAN FRANCISCO" i "san francisco" będą razem. Następnie powinieneś po prostu usunąć "UPPER()" z zapytania, a DB2 powinno wiedzieć, że może użyć twojego indeksu.

Ponownie, jest to oparte wyłącznie na tym, co wiem o programie SQL Server, plus kilka minut na zapoznanie się ze specyfikacją SQL-92; może lub nie może działać dla DB2.

1

DB2 nie jest mocne pod względem zestawiania. I nie ma indeksów opartych na funkcjach.

Sugestia Niek Sanders zadziałałaby, gdyby można było zaakceptować, że haszowanie musi mieć miejsce w twojej aplikacji (ponieważ DB2 nie ma funkcji SHA lub MD5, o ile wiem).

Jednakże, gdybym był tobą, utworzyłbym zmaterializowany widok (MQT == Zmaterializowana tabela zapytań, w języku db2) używając CREATE TABLE AS, dodając kolumnę z wcześniej obliczonym wariantem nazwy. Uwaga: Możesz dodawać indeksy do zmaterializowanych widoków w DB2.

+1

To taniej, zarówno pod względem pamięci, jak i prędkości, aby dodać nową wygenerowaną kolumnę do istniejącej tabeli, a nie całą całą tabelę. I zaprzeczam, że DB2 jest słaba z sortowaniem. I, twoja siostrzana brzydota ... przepraszam, uległem :-). – paxdiablo

5

Krótka odpowiedź, nie.

Długa odpowiedź, tak, jeśli pracujesz na komputerze typu mainframe, ale tak nie jest, więc musisz użyć innych oszustw.

DB2 (od/v8 DB2 LUW) teraz wygenerował kolumny tak można:

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

a następnie utworzyć indeks na ulname. Nie jestem pewien, czy to będzie prostsze.

Wcześniej używałeś kombinacji wstawiania i wyzwalaczy aktualizacji, aby zapewnić synchronizację kolumny ulname i był to koszmar do utrzymania. Również teraz, gdy ta funkcja jest częścią podstawowego DBMS, została zoptymalizowana (jest znacznie szybsza niż rozwiązanie oparte na wyzwalaczu) i nie przeszkadza w uruchamianiu prawdziwych wyzwalaczy dla użytkowników, więc nie ma potrzeby utrzymywania dodatkowych obiektów DB.

Aby uzyskać szczegółowe informacje, patrz here.