2016-06-01 3 views
0

творю онлайн каталог, этот каталог содержит бизнес, это то, как текущая структура таблицы указана:Laravel/MYSQL (Красноречивый) - Запрос большого стола

1) «Бизнес»

  • ID (ПК)
  • Имя
  • phone_number
  • Электронная почта

2) Метки

  • идентификатор (ПК)
  • тег

3) Business_tags

  • ID (ПК)
  • business_id (ФК)
  • tag_id (FK)

В таблице бизнес-таблицы находится более 9 тыс. Строк и более 84 269 строк, а в таблице («Бизнес-таблицы») содержится более 29 тыс. Строк (поскольку бизнес может иметь несколько тегов).

Внутри бизнес-модели, заключается в следующем:

public function tags() 
{ 
    return $this->belongsToMany('App\Tags'); 
} 

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

$business = Business::where(function ($business) use ($request) { 

    $business->whereHas('tags', function ($tag) use ($request) { 

    }); 

})->paginate(20); 

Поиск в среднем занимает 35 секунд для отображения результатов.

Вот исходный SQL:

select * from `businesses` where (exists (select * from `tags` inner join `business_tags` on `tags`.`id` = `business_tags`.`tags_id` where `business_tags`.`business_id` = `businesses`.`id` and `name` in ('chinese'))) 

Это занимает в среднем: 52.4s для запуска внутри Sequel Pro (используя необработанный заявление SQL)

Любые идеи, как я могу улучшить производительность этого запрос, чтобы он был намного быстрее? Я хочу иметь эту функциональность, но пользователь не будет долго ждать ответа!

EDIT:

1 PRIMARY businesses NULL ALL NULL NULL NULL NULL 8373 100.00 Using where 
2 DEPENDENT SUBQUERY business_tags NULL ALL NULL NULL NULL NULL 30312 10.00 Using where 
2 DEPENDENT SUBQUERY tags NULL eq_ref PRIMARY PRIMARY 4 halalhands.business_tags.tags_id 1 10.00 Using where 
+0

Вы можете использовать 'chunk', это ускорит ваш запрос –

+0

Какие индексы вы указали? –

+0

@PaulSpiegel У меня есть индекс. Я установил внешние ключи для каждой таблицы – Phorce

ответ

1

Вы слишком усложняете это и не используете красноречивые отношения правильно. Вы должны использовать JOIN и вместо того, чтобы:

$businesses = Business::join('business_tags', 'business_tags.business_id', '=', 'business.id') 
         ->join('tags', function($join) { 
          $join->on('business_tags.tag_id', '=', 'tags.id') 
           ->where('tags.name', '=', 'chinese'); 
         })->get(); 

Или в необработанном SQL:

SELECT * 
FROM `business` 
INNER JOIN `business_tags` ON `business_tags`.`business_id` = `business`.`id` 
INNER JOIN `tags` ON `business_tags`.`tag_id` = `tags`.`id` AND `tags`.`name` = 'chinese' 

(Обратите внимание, что вы могли бы поставить эту tags.name = 'chinese' часть в ИНЕКЕ и дают тот же эффект)

Ваш в текущем запросе существует подзапрос существует, чтобы получить все записи из сводной таблицы, соответствующие критериям, а затем передать это обратно в основной запрос. Это дополнительный шаг, и это неестественно.

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

Например, если вы хотите увидеть бизнес, вы можете запросить with() телефонные номера и адреса из других таблиц. Вы можете указать свои теги, или sync(). Но красноречивый не строит и не фильтрует запросы, для чего нужен построитель запросов.

Дайте мне знать, если вам нужно больше объяснений.

+0

Спасибо, но это не сработает. Я, например, 28k business_tags связал «tags_id» 1. Запустив запрос, который вы мне дали, просто возвращает 1 строку. Ничего больше. Я не вижу никаких ограничений, так что может быть проблемой? (Ran in laravel и sequal pro) – Phorce

+0

Также к чему относится 'business.business_id'? Как в таблице 'business', есть только столбец' id', а не 'business_id'? – Phorce

+0

Хорошо, я обновил свой ответ с правильными именами таблиц и некоторым сырым sql. Но кроме этого, это должно работать нормально. Сколько у вас тегов? Честно говоря, строки 28k не так много для сводной таблицы. –

0

Как много других, также будет вам сказать.

  1. Запрашиваете ли вы EXPLAIN по вашему запросу?
  2. Добавили ли вы указатели в свои таблицы? Поскольку даже с объемом данных, которые вы упомянули, запрос должен быть быстрее, чем вы сообщили.
  3. Также можете ли здесь работать JOIN и, если быстрее?(просто мысль)
Смежные вопросы