Эффективная работа atomi c bulk refre sh в MariaDB для отношений многие ко многим - PullRequest
0 голосов
/ 29 мая 2020

Мне нужно сохранить список уникальных страниц в таблице pages, связанных отношением «многие ко многим» с таблицей page_providers через таблицу page_xref_page_provider. Мне трудно разработать эффективную операцию atomi c bulk refre sh, состоящую из следующего:

  1. Новый список страниц получен от поставщика страниц. Некоторые страницы в этом списке могут быть такими же, как уже записанные в базе данных (с тем же Url), в то время как некоторые страницы могут быть удалены из списка, а некоторые могут быть добавлены.
  2. Есть некоторые постраничная статистика в базе данных, поэтому я не должен удалять старую страницу (идентифицированную уникальным Url), если есть хотя бы один провайдер страниц, для которого эта страница все еще находится в списке.
  3. Если обновленный список от текущего поставщика страниц не содержит страницу, которую он ранее содержал, и никакой другой поставщик списка страниц не содержит эту страницу в своем списке, страницу следует удалить из таблицы pages.
  4. Страницы которые не зарегистрированы на момент получения списка страниц, должны быть добавлены в таблицу pages и указаны в page_xref_page_provider

То, что я пробовал:

-- We use IGNORE to handle duplicate URLs on the list we received from the current page provider
-- pages_temp is a temporary table whose creation I have omitted
INSERT IGNORE INTO pages_temp (Url, Host, Port) VALUES (?, ?, ?);

BEGIN;

-- In the DB client program, we get the last inserted ID from the following query and the number of
--   rows affected, so to get a range of newly inserted IDs
INSERT IGNORE INTO pages (Url, Host, Port) SELECT Url, Host, Port FROM pages_temp;

-- This doesn't work (wrong syntax), could you correct me here?
-- When preparing this statement, we parameterize it with the current PageProviderID, the
--   last inserted ID (which is actually the first ID in the bulk) and the number of rows inserted
--   plus the first ID in the bulk.
INSERT INTO page_xref_page_provider (PageProviderID, PageID) SELECT ?, i BETWEEN ? AND ?;

-- This query is parametrized with the current page provider ID
DELETE page_xref_page_provider FROM page_xref_page_provider AS pxpp
JOIN pages ON pxpp.PageID = pages.ID AND pxpp.PageProviderID=?
WHERE pages.Url NOT IN (SELECT Url FROM pages_temp);

-- This seems inefficient because the subquery also fetch the relations not affected by the current
--   list of pages / page provider
DELETE FROM pages WHERE pages.ID NOT IN (SELECT DISTINCT PageID FROM page_xref_page_provider);

COMMIT;

1 Ответ

1 голос
/ 31 мая 2020

Избегайте NOT IN ( SELECT ... ). В некоторых ситуациях его производительность ужасна. LEFT JOIN и EXISTS могут работать быстрее.

Есть ли AUTO_INCREMENT идентификаторы в таблицах? Если это так, остерегайтесь IGNORE «идентификаторов горения».

Вот обсуждение техники высокоскоростного приема: http://mysql.rjweb.org/doc.php/staging_table

Советы по производительности для многих -to-many таблицы: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...