Альтернативные способы написания одного и того же SQL-запроса для профилирования / тестирования
Я тестирую базу данных Ingres Vectorwise, чтобы попытаться найти более быстрый способ выполнения запросов, поскольку мы испытываем некоторую медлительность в связи с поиском текста.
Реализация №1 ниже очень быстрая, если я ищу около 5000 элементов на основе столбца char(). К сожалению, поиск 50 элементов занимает примерно столько же времени, сколько и поиск 5000.
Реализация №2, с другой стороны, очень быстрая для 50 элементов, но не масштабируется для 5000 элементов.
Реализация № 3, очевидно, будет хуже, чем № 1, но я просто приводил примеры того, что я пробовал.
У меня такой вопрос: если предположить, что в моей таблице только два столбца: q = bigint, r = char(), можете ли вы придумать какой-либо другой способ написания этого запроса с использованием базового SQL, чтобы у меня было больше вариантов выбора? Я надеюсь, что есть опция, которая работает разумно как для 50, так и для 5000 (та, которая масштабируется так, как вы ожидаете в базе данных).
Обратите внимание, что я приму любой ответ с альтернативными запросами, которые выполняют ту же функцию; чем больше, тем лучше. Я не ожидаю, что что-то изменится так, как я надеюсь, но я не буду знать, пока не попробую больше.
Реализация № 1:
select q
from test_table
where r in ('a', 'b', 'c', 'd', 'e')
Реализация № 2:
select q
from test_table
where r = 'a' or r = 'b' or r = 'c' or r ='d' or r = 'e'
Реализация № 3:
select q
from test_table a
where exists (
select r
from testtable
where r in ('a', 'b', 'c', 'd', 'e')
and a.r = r)
2 ответа
Я могу только предложить объединение / объединение всех в реализации #2, так как объединение может быть быстрее, чем ИЛИ. Реализация № 1 - это то, что мне нравится больше. Он должен использовать индексы и должен быть достаточно быстрым. Например, начиная с Oracle 10g, он автоматически переписывает подзапрос IN для использования EXISTS.
select q
from test_table
where r = 'a'
UNION ALL
select q
from test_table
where r = 'b'
....
Оператор UNION выделяет отдельные строки. UNION ALL выделяет все строки, включая дубликаты. UNION ALL обычно быстрее, чем UNION.
Vectorwise не "масштабируется так, как вы ожидаете", потому что не имеет индексов B-дерева. Он использует метаданные для каждого блока высоких и низких значений, чтобы выбрать, какие блоки читать вместо этого, как и большинство столбчатых аналитических СУБД. Это дает отличную производительность при извлечении множества строк из очень большой таблицы, но при низкой производительности - при вытягивании нескольких строк, так как оно пропускает множество ненужных строк.
Вы можете оптимизировать, отсортировав свою таблицу по 'r', либо вручную, либо с помощью команды "создать индекс" (это предотвратит массовую загрузку после первой загрузки). Это сделает метаданные более точными, поэтому будет прочитано меньше блоков.
Я отмечаю, что в примере только два столбца, без объединений и агрегатных функций. Действительно ли вам нужна колоночная база данных или Lucene будет более подходящей?