Альтернативные способы написания одного и того же 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 будет более подходящей?

Другие вопросы по тегам