Найти, если один из текущих пользователей (3.000) находится в базе данных 5.000.000 строк - PullRequest
2 голосов
/ 30 июня 2019

У меня есть проект laravel, в котором мне нужно периодически проверять, находится ли один из 3.000 пользователей приложения в базе данных Anti-Laundering (5.000.000 больших строк Microsoft SQL таблица).

В веб-интерфейсе я сделал это асинхронно с ajax, поэтому, когда я нажимаю кнопку «Проверить пользователей», я буду ждать ответа.

$users = User::all(); // 3.000 rows

foreach($users as $user){

      $aml = DB::table('anti_money_laundering') // 5.000.000 rows
                ->select('ID')
                ->whereRaw("LOWER([FULL_NAME]) = ?", [$user->full_name])
                ->first();

      if($aml){
            //Bingo, do stuff
            //Continue
      }

}

Но я получаю maximum execution time of 30 seconds ошибку и думаю, что увеличение времени запроса в php.ini конфигурации не является решением моей проблемы.

Как мне это сделать? Какова лучшая практика для больших запросов / длинных запросов?

Ответы [ 2 ]

1 голос
/ 30 июня 2019

В настоящее время вы выполняете запрос внутри цикла - и цикл с 3000 итераций, следовательно, сделает 3000 запросов - это занимает время!

Вместо этого вы можете просто выполнить один запрос, где вы объедините две таблицы и посмотрите, были ли получены какие-либо результаты.

SELECT aml.id
FROM anti_money_laundering AS aml
JOIN users AS u
    ON aml.FULL_NAME = u.full_name

В Eloquent вы можете сделать это следующим образом

$query = DB::table('anti_money_laundering ')
              ->join('users', 'users.full_name', '=', 'anti_money_laundering.full_name')
              ->select('anti_money_laundering.id')
              ->get();

Если есть какие-либо результаты, есть совпадение.

0 голосов
/ 30 июня 2019

Создайте массив с именами пользователей и проверьте, есть ли в вашем наборе какая-либо запись anti_money_laundering:

$users = User::all(); // 3.000 rows
$fullNames = [];

foreach($users as $user){

      $fullNames[]=$user->full_name;

}

$badUsers = DB::table('anti_money_laundering') // 5.000.000 rows
                ->select('ID')
                ->whereIn("LOWER([FULL_NAME]) = ?", $fullNames)
                ->get();

foreach($badUsers as $badUser){
    //Bingo, do stuff
    //Continue
}

Обратите внимание, что я не бегло говорю на Laravel или Eloquent, поэтому, если в моем ответе есть опечатки, то это и есть причина. Однако эта идея превосходит вашу первоначальную идею отправки 3000 запросов (очень медленно) или другого ответа, который приводит к ненужному объединению.

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