Я написал sql для таблицы, которая имеет около 50.000.000 пользователей. Запрос занимает слишком много времени, чем я ожидал, что он не закончил около 23 часов.Как написать эффективный UPDATE-SELECT sql
UPDATE users
SET building_id = B.id
FROM (
SELECT *
FROM buildings B
) AS B
WHERE B.city = address_city
AND B.town = address_town
AND B.neighbourhood = address_neighbourhood
AND B.street = address_street
AND B.no = address_building_no
Идея этого SQL заключается в том, что извлекать данные здания/адреса пользователей и вместо того, чтобы ссылаться на него в таблице зданий.
EXPLAIN
Update on users (cost=22226900.43..22548054.14 rows=15212 width=166)
-> Merge Join (cost=22226900.43..22548054.14 rows=15212 width=166)
Merge Cond: (((users.address_city)::text = (b.city)::text) AND ((users.address_town)::text = (b.town)::text) AND ((users.address_neighbourhood)::text = (b.neighbourhood)::text) AND ((users.address_street)::text = (b.street)::text) AND ((users.address_building_no)::text = (b.no)::text))
-> Sort (cost=21352886.76..21401078.96 rows=96384398 width=156)
Sort Key: users.address_city, users.address_town, users.address_neighbourhood, users.address_street, users.address_building_no
-> Seq Scan on users (cost=0.00..2559921.19 rows=96384398 width=156)
-> Materialize (cost=874013.68..883606.86 rows=9593179 width=63)
-> Sort (cost=874013.68..878810.27 rows=9593179 width=63)
Sort Key: b.city, b.town, b.neighbourhood, b.street, b.no
-> Seq Scan on buildings b (cost=0.00..136253.54 rows=9593179 width=63) (10 rows)
Я не знаю, использует ли SQL внутренний SELECT, SQL для каждого из пользователей или кэши для сделки. Кроме того, если он кэширует, использует ли он индексы для кэшированной таблицы temp?
Я не мог писать SQL так:
FROM (
SELECT *
FROM buildings B
WHERE B.city = users.address_city
AND B.town = users.address_town
AND B.neighbourhood = users.address_neighbourhood
AND B.street = users.address_street
AND B.no = users.address_building_no
)
он говорит, что users
не могут быть доступны из внутреннего выбора. Есть ли у вас предложение получить доступ к зданиям во внутреннем заявлении sql.
первый я не будет использовать select * вместо выбора полей, которые вы действительно используете. Я бы попробовал использовать Toad или другую программу, которая может помочь вам оптимизировать запросы. Также вы можете поговорить с вашим dba, чтобы проверить правильность индексов. – Veelicus
Можете ли вы показать нам вывод 'EXPLAIN' для вашего первого запроса? –
Вы проверили, есть ли активные блокировки таблиц или строк? И, пожалуйста, отпустите подзаголовок, вам это не нужно. –