Учитывая желаемые результаты и информацию базы данных, программно создайте запрос SQL, который дает эти результаты - PullRequest
7 голосов
/ 29 января 2011

Я не думаю, что есть простой способ сделать это, но есть вероятность, что ...

Мне дано несколько списков из примерно 10000 записей, каждый из 10 миллионов записей.Таблица.Данные в настоящее время генерируются запросами по различным неиндексированным элементам.Я хочу автоматически создавать запросы, которые дают одинаковые результаты, используя десять отдельных проиндексированных полей.

Есть ли известный алгоритм для создания чего-то подобного?Я имею в виду не только основы включения каждого индексированного «узла» со своим собственным OR.

Например, предполагая, что нужны следующие данные:

Letter, Number
A, 1
A, 2
B, 1
C, 2

и исходная база данных имеет

Letter, Number
A, 1
A, 2
A, 3
B, 1
C, 1
C, 2
D, 1
D, 3

Я бы хотел что-то вроде:

WHERE ((Letter = 'A' OR Letter = 'B') AND (Number = 1 OR Number = 2)) 
OR (Letter = 'C' and Number = 2)

Или, может быть

WHERE (Letter IN ('A', 'B', 'C') AND Number IN (1, 2) 
AND NOT (Number = 1 AND Letter = 'C'))

Но я думаю Я бы предпочел не иметь

WHERE (Letter = 'A' AND Number = '1') OR 
(Letter = 'A' AND Number = '2') OR
(Letter = 'B' AND Number = '1') OR
(Letter = 'C' AND Number = '2')

- если только эксперты по базам данных не считают, что это будетгораздо более оптимизированный в долгосрочной перспективе, для размера выборки, о котором мы говорим.Время выполнения запросов важно;времени выполнения инструмента конвертации нет.Мне также не нужно обязательно получать «лучший» ответ;«достаточно хорошо» приемлемо.

Мой текущий план состоит в том, чтобы подсчитывать, сортировать и повторять поиск вещей, которые можно сгруппировать, чтобы попытаться создать как можно меньше «группировок»;Я думаю, что я бы предпочел не иметь десять тысяч (A и B и C и D и E и F и G и H и I и J) вместе.

Мысли?Экспертный совет?

Ответы [ 3 ]

1 голос
/ 30 января 2011

Извините, на самом деле это не ответ на ваш вопрос, а мои собственные размышления о проблеме.

Я бы посоветовал хранить ваши списки в отдельной таблице. Это позволит вам сделать объединенный выбор из двух таблиц в конце. Вы можете или не можете использовать индексы в таблице фильтров, в зависимости от тестов производительности с вашими данными.

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

CREATE TABLE t_filter_lists (
    f_letter varchar2(1),
    f_number number
);

-- Optionally, create an index:
CREATE INDEX ix_filter_lists
ON t_filter_lists (
    f_letter,
    f_number
);

INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('A', 1);
INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('A', 2);
INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('B', 1);
INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('C', 2);
COMMIT;

-- (Oracle-specific part) gather statistics on the filter table
EXEC DMBS_STATS.GATHER_TABLE_STATS(...

-- Run your query
SELECT *
FROM t_your_table t
    INNER JOIN t_filter_lists f
        ON  f.f_letter = t.t_letter
        AND f.f_number = t.t_number;

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

0 голосов
/ 31 января 2011

Это на самом деле невозможно без дополнительных ограничений на проблему. Существует буквально бесконечное количество критериев фильтрации, которые вы можете использовать для выбора набора строк в базе данных, и просто невозможно оценить их все. Например, предположим, что представление построено из строк, чьи идентификаторы являются простыми или чьи хэши SHA1 заканчиваются на 0 - можно ли ожидать, что любая автоматизированная процедура сможет обнаружить эти правила?

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

0 голосов
/ 29 января 2011

Одним из решений было бы использование За исключением случаев, когда вы не хотите:

Select Letter, Number
From Table
Except
    (
    Select 'A', 3
    Union All 
    Select 'C', 1
    Union All 
    Select Distinct 'D', Number
    From Table
    )

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

Добавление

Природа алгоритма, используемого для определения ваших критериев, не ясна. Будет ли поиск предметов для включения или исключения? Мои первые два решения предполагают, что вы строите список исключений. Однако, если вы создаете список включений, то, очевидно, вы можете использовать вместо этого Intersect. Кроме того, вы можете уменьшить список, используя конструктор Values:

Select Letter, Number
From Table
Intersect
Select *
From ( Values('A',1)
    , ('A',2), ('A',3), ('B',1), ('C',2) )

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

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