Сведения о вопросе

Faridun

11:57, 25th August, 2020

Теги

sql   database   oracle   indexing   db2    

Индекс Базы Данных Без Учета Регистра?

Просмотров: 701   Ответов: 6

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

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;

Но, конечно, он давится на UPPER(имя).

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

EDIT: я готов выслушать решения для других баз данных... он может перейти на DB2...



  Сведения об ответе

PROGA

22:42, 19th August, 2020

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

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

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

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

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


  Сведения об ответе

qwerty101

02:09, 19th August, 2020

Короткий ответ-нет.

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

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

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

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

До этого вам приходилось использовать комбинацию триггеров insert и update, чтобы обеспечить синхронизацию столбца ulname, и это был кошмар для поддержания. Кроме того, теперь, когда эта функциональность является частью ядра DBMS, она была сильно оптимизирована (это намного быстрее, чем решение на основе триггера) и не мешает реальным пользовательским триггерам, поэтому никаких дополнительных объектов DB для обслуживания не требуется.

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


  Сведения об ответе

COOL

18:41, 19th August, 2020

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

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

где "nvarchar(200)" обозначает любой тип данных вашего текущего столбца. "CI" часть строки сортировки-это то, что помечает ее как нечувствительную к регистру в MSSQL.

Объяснять... я понимаю, что индекс будет хранить значения в порядке сортировки индексированного столбца. Если сделать параметры сортировки столбца нечувствительными к регистру, то индекс будет хранить 'San Francisco', 'SAN FRANCISCO' и 'san francisco' все вместе. Тогда вам нужно просто удалить "UPPER()" из вашего запроса, и DB2 должен знать, что он может использовать ваш индекс.

Опять же, это основано исключительно на том, что я знаю о сервере SQL, плюс пара минут просмотра спецификации SQL-92; она может работать или не работать для DB2.


  Сведения об ответе

SSESION

21:54, 17th August, 2020

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

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


  Сведения об ответе

padenie

09:54, 16th August, 2020

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

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

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


  Сведения об ответе

LIZA

12:11, 27th August, 2020

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

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться