Индекс нечувствительный к регистру базы данных? - PullRequest
6 голосов
/ 16 августа 2008

У меня есть запрос, в котором я ищу строку:

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

Теперь это работает нормально, но не очень хорошо масштабируется, и мне нужно оптимизировать его. Я нашел вариант в соответствии с принципами создания сгенерированного представления или что-то подобное, но я надеялся на более простое решение с использованием индекса.

Мы используем DB2, и я действительно хочу использовать выражение в индексе , но эта опция, по-видимому, доступна только в z / OS, однако мы используем Linux. Я все равно попробовал индекс выражения:

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

Но, конечно, он задыхается от ВЕРХНЯ (имя).

Есть ли другой способ, которым я мог бы создать индекс или что-то подобное таким образом, чтобы мне не приходилось реструктурировать мои существующие запросы, чтобы использовать новое сгенерированное представление, или изменить мои существующие столбцы, или любые другие подобные навязчивые изменения?

РЕДАКТИРОВАТЬ: я открыт для прослушивания решений для других баз данных ... это может перенести на DB2 ...

Ответы [ 6 ]

7 голосов
/ 16 августа 2008

Вы можете добавить индексированный столбец, содержащий числовой хэш-ключ названия города. (С учетом дубликатов).

Тогда вы можете сделать мульти-предложение, где:

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

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

Кроме того, просмотрите руководство по БД и посмотрите варианты создания табличных индексов. Там может быть что-то полезное.

5 голосов
/ 07 января 2009

Краткий ответ, нет.

Длинный ответ, да, если вы работаете на мэйнфрейме, но это не так, вам придется использовать другие хитрости.

DB2 (начиная с DB2 / LUW v8) теперь генерирует столбцы, поэтому вы можете:

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

и затем создайте индекс для ulname. Я не уверен, что вы поймете это проще, чем это.

До этого вам приходилось использовать комбинацию триггеров вставки и обновления, чтобы обеспечить синхронизацию столбца ulname, и это было кошмаром. Кроме того, теперь, когда эта функциональность является частью базовой СУБД, она сильно оптимизирована (она намного быстрее, чем решение на основе триггеров) и не мешает действительным пользовательским триггерам, поэтому никаких дополнительных объектов БД для обслуживания не требуется. 1010 *

Подробнее см. здесь .

1 голос
/ 04 сентября 2008

DB2 не сильна в отношении сортировки. И у него нет индексов на основе функций.

Предложение Niek Sanders сработает, если вы согласитесь с тем, что хеширование должно происходить в вашем приложении (насколько я знаю, у DB2 нет функций SHA или MD5).

Однако на вашем месте я бы создал материализованное представление (MQT == Materialized Query Table, на языке db2), используя CREATE TABLE AS , добавив столбец с предварительно вычисленным верхним вариант варианта имени. Примечание: Вы можете добавить индексы к материализованным представлениям в DB2.

1 голос
/ 19 августа 2008

Я не знаю, будет ли это работать в DB2, но я расскажу вам, как бы я это делал в SQL Server. Я думаю, способ, которым MSSQL делает это, является стандартом ANSI, хотя конкретные строки сортировки могут отличаться. В любом случае, если вы можете сделать это, не удаляя остальную часть вашего приложения - есть ли другие места, где столбец «name» должен быть чувствительным к регистру? - попробуйте сделать весь столбец без учета регистра, изменив параметры сортировки, а затем индексируйте столбец.

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 голос
/ 16 августа 2008

PostgreSQL также поддерживает индексирование результатов функции:

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

Единственный другой вариант, который я могу придумать, - это немного нормализовать ваши данные, создав еще один столбец для хранения версии в верхнем регистре (обновленной с помощью триггеров) и индексирования ее. Blech!

1 голос
/ 16 августа 2008

Oracle поддерживает функционально-ориентированные индексы. Их канонический пример:

 create index emp_upper_idx on emp(upper(ename));  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...