Как обработать длинный сложный SQL запрос на обновление? - PullRequest
0 голосов
/ 19 апреля 2020

У меня есть этот код, который никогда не завершается.

Вот что происходит:

  1. Мы делаем вызов API, чтобы получить большие данные, и нам нужно проверить, есть ли В отличие от нашей базы данных, нам нужно обновить нашу БД для этой указанной строки c. Количество строк будет увеличиваться по мере роста проекта, в некоторых случаях go может превышать 1 миллиард строк.

Проблема в том, что даже при обновлении 1 миллиарда строк это работает

Чтобы смоделировать это, я сделал 9000 для l oop
<?PHP 
ini_set("memory_limit","-1");
 ignore_user_abort(true);
for ($i=0; $i < 9000; $i++) { 
  // Complex SQL UPDATE query that requires joining tables,
  // and doing search and update if matches several variables
}

//here I have log function to see if for loop has been finished

Если я l oop, это 10 раз, это все еще требует времени, но это работает и записывает, но с 9000 это не завершает sh l oop и никогда ничего не записывает.

Примечание: я добавил ini_set("memory_limit","-1"); ignore_user_abort(true); для предотвращения ошибок памяти.

Есть ли способ сделать это масштабируемым?

Подробности: Я делаю этот запрос 2 раза в день

1 Ответ

0 голосов
/ 19 апреля 2020

Не зная специфики API, как часто вы его называете, сколько данных он возвращает за раз, и сколько информации вам действительно нужно хранить, трудно дать вам конкретные c ответы. В целом, однако, я бы подошел к этому так:

У сценария «продюсер» запросите API на любой основе, но вместо того, чтобы выполнять сложное обновление SQL, просто сохраните данные локально (предположительно в таблице, назовем их tempTbl). Это должно гарантировать, что он работает относительно быстро. Реализуйте временную метку в этой таблице, чтобы вы знали, когда были вставлены записи. В идеальном мире при следующем запуске этого сценария «производителя», если он обнаружит какие-либо данные из API, уже существующего в tempTbl, он перезапишет его новыми данными (и обновит последнюю обновленную метку времени). Это гарантирует, что tempTbl всегда содержит последние кэшированные обновления от API.

У вас также будет скрипт «потребителя», который выполняется регулярно и который обрабатывает данные из tempTbl (предположительно в LIFO порядок, но может быть в любом порядке вы хотите). Этот «потребительский» скрипт будет обрабатывать, скажем, 100 записей из tempTbl, делать на них комплекс SQL ОБНОВЛЕНИЕ и удалять их из tempTbl.

Идея состоит в том, что один скрипт («производитель») постоянно заполняет tempTbl, в то время как другой сценарий («потребитель») постоянно обрабатывает элементы в этой очереди. Предположительно, «потребитель» быстрее, чем «производитель», иначе tempTbl станет слишком большим. Но благодаря интеллектуальной схеме и тщательному регулированию частоты выполнения каждого сценария можно надеяться, что вы сохраните застой.

Я также предполагаю, что эти два сценария будут запускаться как задания cron, что означает, что вам просто нужно настроить сколько записей они обрабатывают за один раз, а также как часто они запускаются. Теоретически нет причины, по которой «потребитель» не может просто обработать все ожидающие записи, хотя на практике это может привести к чрезмерной нагрузке на вашу БД, поэтому вы можете захотеть ограничить ее несколькими (десятками, сотнями, тысячами или миллионами? ) записей за один раз.

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