У меня есть функция внизу, которая пытается сопоставить пользователей с определенными полями белого списка, которые работают блестяще, для небольших объемов данных, но в нашей производственной среде мы можем иметь> 1 миллион записей пользователей, а Eloquent (по понятным причинам) медленный при создании моделей в: $query->get()
в конце. Сегодня утром я задал вопрос о том, как ускорить это, и принятый ответ был блестящим и обработанным, единственной проблемой сейчас является то, что полученный запрос отправляется в DB::select($query->toSql()...
потерял всю необходимую дополнительную реляционную информацию, в которой я нуждаюсь. Таким образом, есть какой-либо способ (сохраняя как можно больше текущей функции), добавлять добавления к DB::select
чтобы я мог поддерживать скорость и не терять отношения, или потребуется ли полная переписывание?
Запрос recipients
должен включать отношения для тегов, контактную информацию, настройки контактов и т. Д., Но полученный sql из $query->toSql()
не имеет объединений и ссылается только на одну таблицу.
public function runForResultSet() { $params = []; // Need to ensure that when criteria is empty - we don't run if (count($this->segmentCriteria) <= 0) { return; } $query = Recipient::with('recipientTags', 'contactDetails', 'contactPreferences', 'recipientTags.tagGroups'); foreach ($this->segmentCriteria as $criteria) { $parts = explode('.', $criteria['field']); $fieldObject = SegmentTableWhiteListFields::where('field', '=', $parts[1])->get(); foreach ($fieldObject as $whiteList) { $params[0] = [$criteria->value]; $dateArgs = ((strtoupper($parts[1]) == "AGE" ? false : DatabaseHelper::processValue($criteria))); if ($dateArgs != false) { $query->whereRaw( DatabaseHelper::generateOperationAsString( $parts[1], $criteria, true ), [$dateArgs['prepared_date']] ); } else { // Need to check for empty value as laravel's whereRaw will not run if the provided // params are null/empty - In which case we need to use whereRaw without params. if (!empty($criteria->value)) { $query->whereRaw( \DatabaseHelper::generateOperationAsString( $parts[1], $criteria ), $params[0] ); } else { $query->whereRaw( \DatabaseHelper::generateOperationAsString( $parts[1], $criteria ) ); } } } } // Include any tag criteria foreach ($this->segmentRecipientTagGroupCriteria as $criteria) { $startTagLoopTime = microtime(true); switch (strtoupper($criteria->operator)) { // IF NULL check for no matching tags based on the tag group case "IS NULL": $query->whereHas( 'recipientTags', function ($subQuery) use ($criteria) { $subQuery->where('recipient_tag_group_id', $criteria->recipient_tag_group_id); }, '=', 0 ); break; // IF NOT NULL check for at least 1 matching tag based on the tag group case "IS NOT NULL": $query->whereHas( 'recipientTags', function ($subQuery) use ($criteria) { $subQuery->where('recipient_tag_group_id', $criteria->recipient_tag_group_id); }, '>=', 1 ); break; default: $query->whereHas( 'recipientTags', function ($subQuery) use ($criteria) { $dateArgs = (DatabaseHelper::processValue($criteria)); $subQuery->where('recipient_tag_group_id', $criteria->recipient_tag_group_id); if ($dateArgs != false) { $subQuery->whereRaw( DatabaseHelper::generateOperationAsString( 'name', $criteria, true ), [$dateArgs['prepared_date']] ); } else { // Need to check for empty value as laravel's whereRaw will not run if the provided // params are null/empty - In which case we need to use whereRaw without params. if (!empty($criteria->value)) { $subQuery->whereRaw( \DatabaseHelper::generateOperationAsString( 'name', $criteria ), [$criteria->value] ); } else { $subQuery->whereRaw( \DatabaseHelper::generateOperationAsString( 'name', $criteria ) ); } } }, '>=', 1 ); } } //$collection = $query->get(); // slow when dealing with > 25k rows $collection = DB::select($query->toSql(), $query->getBindings()); // fast but loses joins / relations // return the response return \ApiResponse::respond($collection); }
Потеряв реляционную информацию, вы имеете в виду отношения, которые с нетерпением загружают имя, с которым вы передали () ?
Эта информация не была потеряна, поскольку она никогда не была в запросе . Когда вы загружаете такие отношения, Eloquent запускает отдельные SQL-запросы для извлечения связанных объектов для объектов из вашего основного набора результатов.
Если вы хотите, чтобы столбцы из этих отношений находились в вашем результирующем наборе, вам нужно явно добавлять объединения к вашему запросу. Вы можете найти информацию о том, как это сделать в документации: https://laravel.com/docs/5.1/queries#joins