#mysql #sql #sql-server #oracle #indexing
#mysql #sql #sql-сервер #Oracle #индексирование
Вопрос:
У меня есть таблица, содержащая пары ключ-значение, по которым я хотел бы иметь возможность эффективного поиска:
SELECT * WHERE meta_key = "User ID" AND meta_value = "123userId";
Однако из-за устаревшего требования размер хранилища ключей и значений NVARCHAR может достигать 255 и 1000 символов соответственно. Индексация на таких больших столбцах не только дорогостоящая, но и прямо ограничена для некоторых типов БД.
Я полагаю, что в MySQL есть система, позволяющая индексировать по LEFT
подстроке в стиле a следующим образом:
CREATE INDEX ix_metadata_indexing_key_value ON metadata_indexing(meta_key, meta_value(255));
… однако наша система должна поддерживать все три MySQL, MSSQL и Oracle. Правильно ли это, и если да, то как мне создать аналогичные индексы в MSSQL и Oracle?
Комментарии:
1. Если вам нужно решение здесь, вам, вероятно, понадобятся разные решения для каждого поставщика. Все 3 используют очень разные диалекты. Для SQL Server я бы предложил добавить
PERSISTED
вычисляемый столбец и проиндексировать его; затем вы можете запросить это вWHERE
вместо. Хотя, учитывая, что вам нужна толькоLEFT
сторона, aLIKE
, вероятно, sargable тожеWHERE YourColumn LIKE '123userid%';
будет использовать индекс для вашего столбцаYourColumn
.2. Также стоит отметить, что в стандарте ANSI SQL вообще ничего не говорится об индексации. Каждый поставщик изобретает свой собственный проприетарный синтаксис и функции для индексации. Вам нужно подумать о шаблоне адаптера , потому что нет синтаксиса, который будет работать во всех реализациях поставщиков.
3. Это звучит как преждевременная оптимизация, так и проблема XY . Считаете ли вы такой ограниченный индекс полезным?
4. «звучит как проблема x-y». Также звучит как дизайн EAV, одна из худших концепций, когда-либо навязанных миру СУБД.
5. Как говорили другие, решения, не зависящего от базы данных, не существует. Для Oracle я бы посмотрел на индексы на основе функций.
Ответ №1:
Если вы говорите о WordPress, этот индекс является только частью решения. При достижении into postmeta
вам нужен составной ключ, начинающийся с. post_id
Больше рекомендаций здесь .
Кроме того, если данные достаточно предсказуемы, вы могли бы заменить LONGTEXT
will чем-то более цивилизованным, например VARCHAR(150)
. Сделайте SELECT MAX(LENGTH(meta_key)), MAX(LENGTH(meta_value)) FROM post_meta;
.
(Я тоже просматриваю EAV. И особенно плохая реализация WP.)
Комментарии:
1. Нет, не для WordPress, полностью на заказ
2. @Arachin — Хорошо, проверьте мою ссылку, чтобы узнать, не перепутали ли они индексы.
Ответ №2:
Как и предполагал @Larnu, в итоге мы получили новый вычисляемый meta_value_short
столбец, который нужно было создавать отдельно для каждого типа БД. При запросе…
Если длина равна 255 или меньше: просто сравните с meta_value_short
.
В противном случае: сначала сравните LEFT(value, 255)
с meta_value_short
, затем дополнительно сравните с meta_value
.
Для справки определения вычисляемых столбцов приведены ниже:
MSSQL:
ALTER TABLE [metadata_indexing] ADD meta_value_short AS (SUBSTRING(meta_value, 1, 255))
MySQL:
ALTER TABLE metadata_indexing ADD meta_value_short VARCHAR(255) AS (SUBSTRING(meta_value, 1, 255));
Oracle:
ALTER TABLE metadata_indexing ADD meta_value_short AS (SUBSTR(meta_value, 1, 255));