Запрос для извлечения старых данных (импортированных из идентичных БД) и новых данных с помощью объединений

Кратко: я импортировал данные из существующих приложений с идентичными базами данных. Существует множество таблиц, поэтому обновление данных с помощью новых идентификаторов было невозможно. Существующий первичный ключ для каждой таблицы, например, serviceprovider - sp_id. Для всех таблиц я добавил новый идентификатор первичного ключа. Мне нужно получить старые и новые данные (после импорта) из этих таблиц. Чтобы получить старые данные, я использую старые первичные / внешние ключи и сравниваю database_id для таблиц, из которых они соединяются, откуда они были импортированы. Новые данные используют только новый идентификатор первичного ключа. Я знаю, если это новые данные по тому факту, что старый первичный ключ имеет значение 0.

select serviceprovider.* from serviceprovider sp
inner join services ss on ((sp.id = ss.sp_id) AND (ss.ss_id = 0))
OR ((sp.sp_id = ss.sp_id) AND (ss.ss_id <> 0) AND (sp.database_id=ss.database_id))

Я построил этот запрос, который становится очень медленным по мере увеличения данных. Первоначально это работало хорошо, но когда я импортировал данные из старых баз данных, он почти перестал работать. Как вы можете догадаться, мне нужно присоединиться к большему количеству таблиц, чтобы получить полные данные. Все таблицы используют один и тот же механизм объединения. Я использую MySQL. Можно ли перестроить запрос, чтобы повысить производительность?

1 ответ

Решение

Этот запрос не должен быть таким тяжелым, пожалуйста, рассмотрите возможность добавления индекса для всех соединяемых таблиц:

serviceprovider(id,sp_id,database_id)

services(sp_id,ss_id,database_id)

Это должно ускорить этот запрос.

Вы также можете попытаться перестроить свой запрос с помощью EXISTS() вместо внутреннего соединения:

select serviceprovider.* from serviceprovider sp
WHERE EXISTS(select 1 from services ss
             where ((sp.id = ss.sp_id) AND (ss.ss_id = 0))
                    OR ((sp.sp_id = ss.sp_id) AND (ss.ss_id <> 0) AND (sp.database_id=ss.database_id)))

Возможно, он будет работать быстрее.

РЕДАКТИРОВАТЬ: Давайте попробуем другой подход, два выбора и объединение вместо этого условия ИЛИ:

select serviceprovider.* from serviceprovider sp
inner join services ss on (sp.id = ss.sp_id AND ss.ss_id = 0)
UNION ALL
select serviceprovider.* from serviceprovider sp
inner join services ss on(sp.sp_id = ss.sp_id AND ss.ss_id <> 0 AND sp.database_id=ss.database_id)
Другие вопросы по тегам