2017-10-17 80 views
4

我想申請where條件關係。這是我做的:差在哪裏Laravel性能

Replay::whereHas('players', function ($query) { 
    $query->where('battletag_name', 'test'); 
})->limit(100); 

生成下面的查詢:

select * from `replays` 
where exists (
    select * from `players` 
    where `replays`.`id` = `players`.`replay_id` 
     and `battletag_name` = 'test') 
order by `id` asc 
limit 100; 

其中在70秒執行。如果我手動重寫這樣的查詢:

select * from `replays` 
where id in (
    select replay_id from `players` 
    where `battletag_name` = 'test') 
order by `id` asc 
limit 100; 

它在0.4秒內執行。爲什麼where exists是默認行爲,如果它太慢?有沒有辦法使用查詢生成器生成正確的where in查詢,還是需要注入原始SQL?也許我完全搞錯了什麼?

replays表有4M行,players有40M行,所有相關列都被索引,數據集不適合MySQL服務器內存。

更新:發現正確的查詢可以產生如下:

Replay::whereIn('id', function ($query) { 
    $query->select('replay_id')->from('players')->where('battletag_name', 'test'); 
})->limit(100); 

還有一個問題,爲什麼exists表現這麼糟糕,爲什麼它是默認的行爲

+0

更快的查詢我建議不要選擇* ..嘗試選擇特定的屬性而不是全部。 – parkway

+0

我需要爲我的情況選擇所有這些。即使只選擇「id」列,查詢性能也會提高不到1%,因此可以忽略不計。 – Poma

回答

1

我覺得表現不取決於在哪裏只有它取決於你選擇了多少記錄

再加上試圖優化你的mysql服務器

https://dev.mysql.com/doc/refman/5.7/en/optimize-overview.html

,同時優化你的PHP服務器

,如果你有你爲什麼不使用原始查詢對象從幼蟲

$replay = DB::select('select * from replays where id in (
select replay_id from players where battletag_name = ?) 
order by id asc limit 100', ['test'] 
); 
+0

這兩個查詢都會因爲「limit」子句而精確選擇100行。哪裏有70秒,哪裏有0.4秒。優化與問題無關,因爲它們將減少查詢執行時間。 – Poma

+0

然後,也許你可以使用上面提到的原始查詢 –

+0

真實應用程序中的查詢比有很多條件的查詢更復雜,我真的需要查詢生成器。從大量的原始字符串部分構建它將使我的代碼變成意大利麪條。 – Poma