Как оптимизировать медленный запрос на удаление (удалить данные, которые не используются в другой таблице) в Postgresql - PullRequest
0 голосов
/ 20 октября 2010

У меня есть 2 таблицы (имя (поля)):

data(object_id, property_id, value_id)

и

string(id, value)

Все данные находятся в «строковой» таблице.«данные» относятся только к соответствующим строкам.

Например, у меня есть:

data(1,2,3)  
data(1,4,5)  
data(6,4,7)



string(1, 'car')  
string(2, 'color')  
string(3, 'red')  
string(4, 'make')  
string(5, 'audi')  
string(6, 'car2')  
string(7, 'toyota') 

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

, если я удаляю данные (6,4,7), тогда строки с идентификаторами 6 и 7 будут удалены (потому что они больше не используются);4 используется в другой строке данных и поэтому не удаляется.

У меня вопрос, как написать оптимизированный запрос на удаление для таблицы строк?

В настоящее время у меня есть что-то вродето (что работает, но очень медленно):

delete  
from string s  
where 1=1  
and (select count(id) from data where object_id = s.id) = 0  
and (select count(id) from data where property_id = s.id) = 0  
and (select count(id) from data where value_id = s.id) = 0

Я также пытался (в зависимости от количества сирот дает иногда результат на 10-20% быстрее):

delete from string  
where (id not in (select usedids.id from (select object_id as id from data  
    union  
    select property_id as id from data  
    union  
    select value_id as id from data) as usedids)  
);

Iиметь около 100 тыс. строк в обеих таблицах.Если я удалю около 6000 строк в таблице данных, то очистка таблицы строк займет около 3 минут.У меня есть индекс по каждому полю.У меня также есть ограничения внешнего ключа.

Ответы [ 2 ]

1 голос
/ 20 октября 2010

Вы хотите EXISTS.

delete  
from string s  
where 1=1  
and (select count(id) from data where object_id = s.id) = 0  

на самом деле правильно сделано как

delete from string s
where not exists ( select * from data d where d.object_id = s.id)

На самом деле вы не хотите count, а просто хотите узнать, не является ли подтаблица exists.


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

0 голосов
/ 20 октября 2010

проблема, по-видимому, в том, что вы обращаетесь к своей таблице данных 3 раза, а не один раз.

ваш запрос должен быть

УДАЛИТЬ ИЗ СТРОКИ ГДЕ (ВЫБРАТЬ счетчик (*) ОТ данных ГДЕ object_id =s.id ИЛИ property_id = s.id ИЛИ value_id = s.id) = 0;

Еще не пробовал, но я могу внести изменения, если вы сообщите мне, что произошло.

...