Как я могу ускорить различие между таблицами? - PullRequest
1 голос
/ 14 июня 2011

Я работаю над выполнением различий между таблицами в postgresql, это занимает много времени, так как каждая таблица ~ 13 ГБ ... Мой текущий запрос:

SELECT * FROM tableA EXCEPT SELECT * FROM tableB;

и

SELECT * FROM tableB EXCEPT SELECT * FROM tableA;

Когда я выполняю diff для двух (неиндексированных) таблиц, это занимает 1:40 часа (1 час и 40 минут). Чтобы получить как новые, так и удаленные строки, мне нужно выполнить запрос дважды, получив общее количествовремя до 3:30 часов.

Я запустил запрос Postgresql EXPLAIN, чтобы узнать, что он делает.Похоже, что он сортирует первую таблицу, затем вторую, а затем сравнивает их.Это заставило меня задуматься о том, что если бы я проиндексировал таблицы, они были бы предварительно отсортированы, и запрос diff был бы намного быстрее.

Индексирование каждой таблицы заняло 45 минут.После индексации каждый Diff занял 1:35 часа.Почему индексы сбрасывают только 5 минут от общего времени различий?Я бы предположил, что это будет больше половины, так как в неиндексированных запросах я сортирую каждую таблицу дважды (мне нужно выполнить запрос дважды)

Поскольку одна из этих таблиц не будет сильно меняться, она будетнужно только проиндексировать один раз, другой будет обновляться ежедневно.Таким образом, общее время выполнения для индексированного метода составляет 45 минут для индекса, плюс 2x 1:35 для разницы, что дает в общей сложности 3:55 часов, почти 4 часа.

Что я делаю здесь неправильно, яне могу понять, почему с индексом мое время различий в сети больше, чем без него?

Это небольшая ссылка на мой другой вопрос здесь: Postgresql UNION занимает в 10 раз больше времени, чем работает индивидуумзапросы

РЕДАКТИРОВАТЬ: Вот схема для двух таблиц, они идентичны, кроме имени таблицы.

CREATE TABLE bulk.blue
(
  "partA" text NOT NULL,
  "type" text NOT NULL,
  "partB" text NOT NULL
)
WITH (
  OIDS=FALSE
);

Ответы [ 4 ]

2 голосов
/ 14 июня 2011

В приведенных выше инструкциях вы не используете индексы.

Вы можете сделать что-то вроде:

SELECT * FROM tableA a
  FULL OUTER JOIN tableB b ON a.someID = b.someID

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

SELECT * FROM tableA a
  FULL OUTER JOIN tableB b ON a.someID = b.someID
  WHERE ISNULL(a.someID) OR ISNULL(b.someID)

Это должно дать вам строки, которые отсутствовали в таблице A ИЛИ таблице B

1 голос
/ 14 июня 2011

Подтвердите, что ваши индексы используются (они, вероятно, не входят в такой универсальный, кроме оператора), но вы не объединяетесь с указанным столбцом (столбцами), так что вероятность явного объединения не приведет к оптимизированному запросу:

http://www.postgresql.org/docs/9.0/static/indexes-examine.html

Это поможет вам более четко просмотреть анализ объяснения:

http://explain.depesz.com

Кроме того, убедитесь, что вы выполняете анализ натаблица после создания индекса, если вы хотите, чтобы он сразу работал хорошо:}

0 голосов
/ 14 июня 2011
  • Какой индекс вы применили? Индексы полезны только для улучшения условий WHERE. Если вы делаете select *, вы захватываете все поля, и индекс, вероятно, ничего не делает, а занимает пространство и добавляет немного дополнительной обработки за кулисы для механизма обработки данных, чтобы сравнить запрос кеш индекса.

  • Вместо SELECT * вы можете попробовать выбрать уникальные поля и создать индекс для этих уникальных полей

  • Вы также можете использовать OUTER JOIN для отображения результатов из обеих таблиц, которые не совпадают в уникальных полях
  • Вы можете рассмотреть вопрос о кластеризации ваших таблиц
  • Какую версию Postgres вы используете?
  • Когда вы в последний раз пылесосили?

Помимо вышесказанного, 13 ГБ довольно большой, поэтому вы должны проверить настройки конфигурации. Это не займет несколько часов, если у вас недостаточно памяти в вашей системе.

0 голосов
/ 14 июня 2011

Запросы, как указано, требуют сравнения каждого столбца таблиц.

Например, если tableA и tableB имеют по пять столбцов, каждый запрос должен сравнить tableA.col1 с tableB.col1, tableA.col2 с tableB.col2,. , , tableA.col5 to tableB.col5

Если есть только несколько столбцов, которые однозначно идентифицируют запись, а не все столбцы в таблице, то объединение таблиц в определенных столбцах, которые уникально идентифицируют запись, улучшит вашу производительность.

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

...