Эффективный способ выражения нескольких пар кортежей, где условия в выражении SQL - PullRequest
0 голосов
/ 17 августа 2010

Я хочу выполнить SQL-запрос, который логически эквивалентен следующему:

DELETE FROM pond_pairs
WHERE
  ((pond1 = 12) AND (pond2 = 233)) OR
  ((pond1 = 12) AND (pond2 = 234)) OR
  ((pond1 = 12) AND (pond2 = 8)) OR
  ((pond1 = 13) AND (pond2 = 6547)) OR
  ((pond1 = 13879) AND (pond2 = 6))

У меня будут сотни тысяч pond1 - pond2 пар.У меня есть индекс на (pond1, pond2).

Мои ограниченные знания SQL предложили несколько подходов:

  1. Выполнить весь запрос как есть.
  2. Пакетный запросна более мелкие запросы с условиями n WHERE
  3. Сохраните пары pond1 - pond2 в новой таблице и выполните подзапрос в предложении WHERE, чтобы определить
  4. Преобразуйте логику python, которая идентифицирует строки для удаления, в хранимую процедуру.Обратите внимание, что я не знаком с программированием хранимых процедур, и, следовательно, это может потребовать крутой кривой обучения.

Я использую postgres, если это уместно.

Ответы [ 3 ]

1 голос
/ 17 августа 2010

Для удаления большого количества пар pond1-pond2 в одном DELETE я бы создал временную таблицу и присоединился к ней.

-- Create the temp table:
CREATE TEMP TABLE foo AS SELECT * FROM (VALUES(1,2), (1,3)) AS sub (pond1, pond2);

-- Delete
DELETE FROM bar 
USING  
  foo -- the joined table
WHERE 
  bar.pond1= foo.pond1 
AND 
  bar.pond2 = foo.pond2;
1 голос
/ 17 августа 2010

Я сделаю 3. (с JOIN, а не подзапросом) и измерим время запроса DELETE (без создания таблицы и вставки).Это хорошая отправная точка, потому что ПРИСОЕДИНЕНИЕ - очень распространенная и оптимизированная процедура, поэтому в этот раз будет трудно победить.Затем вы можете сравнить это время с вашим текущим подходом.

Также вы можете попробовать следующий подход:

  1. Сортировать пары так же, как в индексе.
  2. Удалить, используяСпособ 2. из вашего описания (вероятно, в одной транзакции).

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

0 голосов
/ 17 августа 2010

С сотнями тысяч пар вы не можете выполнить 1 (выполнить запрос как есть), потому что оператор SQL будет слишком длинным.

3 хорошо, если пары уже есть в таблице.Если нет, вам нужно будет сначала вставить их.Если они вам позже не понадобятся, вы можете запустить то же количество операторов DELETE вместо операторов INSERT.

Как насчет подготовленного оператора в цикле, возможно, пакетного (если Python поддерживает это)

  1. начать транзакцию
  2. подготовить оператор "DELETE FROM pond_pairs WHERE ((pond1 =?) AND (pond2 =?))"
  3. цикл над вашими данными (в Python)и запустите оператор с одной парой (или добавьте в пакет)
  4. commit

Откуда поступают пары?Если вы можете написать операторы SELECT для их идентификации, вы можете просто переместить это условие в предложение WHERE вашего удаления.

DELETE FROM pond_pairs WHERE (pond1, ponds) in (SELECT pond1, pond2 FROM ......  )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...