ускорение постфикса поиска по шаблону еще больше - PullRequest
3 голосов
/ 13 февраля 2012

Я недавно задал вопрос об ускорении поиска текста с подстановочными знаками, например SELECT a, b, c FROM t WHERE a LIKE 'abcde%' в Pg. Наконец, благодаря реализации следующего индекса я могу получать от 200 до 800 мс на запрос.

CREATE INDEX idxa ON t (Lower(a) varchar_pattern_ops);

Теперь я заинтересован в ускорении запроса на порядок, если это возможно; возможно, между 200-800 микросекундами. Можно ли это сделать?

Вся таблица занимает около 1 ГБ необработанного текста (~ 8 миллионов + строк), и ее можно сделать еще меньше, чтобы она легко помещалась в памяти. Могу ли я реализовать кеш поверх Pg, кеш, который будет заполняться со временем? Возможно, memcached или что-то еще. Поскольку большинство кэшей имеют точный поиск по ключу, как мне выполнить поиск по шаблону из кэша?

Кстати, для справки я загрузил всю таблицу в Mongodb, и, хотя я получил очень быстрый поиск при точном поиске a = 'abcdefg', поиск по шаблону Mongodb, как и выше, фактически уступал таковому в Postgres.

1 Ответ

4 голосов
/ 14 февраля 2012

Вы все еще можете выжать немного.

Во-первых, я бы вообще советовал использовать тип данных text вместо varchar.Так что text_pattern_ops вместо varchar_pattern_ops.Однако это не повлияет на производительность.


Далее, поскольку ваш столбец содержит до 100 символов, но вы используете только первые n (20?) Символов, индекс будет намного меньше с lower(left(a, 20) вместо lower(a), как я уже предлагал в своем ответе на ваш вопрос к приквелу .

Сам поиск по индексу выполняет то же самое, но сервер должен посетить еще много страниц на диске илив оперативной памятиМеньше строк будет помещаться в ОЗУ или на страницу диска, поэтому для каждого поиска нужно посещать больше страниц.Кроме того, страницы будут выпадать из вашего кэша раньше и т. Д. Это особенно важно для больших таблиц, подобных вашей.Ограничьте диапазон букв, которые можно искать, до необходимого минимума.Это дает вам что-то вроде:

CREATE INDEX t_a_lower_left_idx ON t (lower(left(a, 20)) text_pattern_ops);

Кроме того, вы можете использовать специальные операторы ~>=~ и ~<~ в своем запросе, как я продемонстрировал в ответе , с которым я связан :

SELECT * FROM tbl WHERE lower(a) ~>=~ 'abcde' AND lower(a) ~<~ ('abcdf')

Обратите внимание на 'f' вместо 'e' во втором выражении.Вопрос в том, как получить «следующий» символ в соответствии с локалью «C»?

SELECT chr(ascii('é')+1));

Итак, вы можете:

SELECT * FROM tbl WHERE lower(a) ~>=~ 'abcde'
                    AND lower(a) ~<~ ('abcd' || chr(ascii('e')+1))

Я выполнил тест с использованием таблицы в натуральном выражении.полмиллиона строк.Поисковый термин, дающий 650 строк, занял 4 мс с первым запросом и 3 мс со вторым.Это очень во многом зависит от того, сколько строк найдено.Для поискового термина, дающего только 1 строку, здесь требуется 0,044 мс.


Поэтому ограничьте минимальную длину поискового термина, чтобы запретить бесполезные запросы, которые в любом случае приводили бы к слишком большому количеству строк.Как минимум 3 или 4 символа.


Далее вы можете кластер свою таблицу следующим образом:

CLUSTER tbl USING t_a_lower_left_idx

После этого мой тестовый сценарий занял 2,5 мс вместо3 мс.


Конечно, применяются все базовые рекомендации по оптимизации производительности .


Если приведенного выше недостаточно, вы можете захотетьподумать о создании табличного пространства на виртуальном диске или в разделе tmpfs (Linux) и создать там индексы или даже поместить всю таблицу целиком.Я уверен, что вы знаете о последствиях для безопасности изменчивой среды для базы данных.Делайте это только в том случае, если вы можете позволить себе потерять все свои данные.

CREATE INDEX t_a_lower_left_idx ON t (lower(left(a, 20)) text_pattern_ops)
TABLESPACE indexspace;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...