2017-05-04 251 views
1

我使用MySQL和我有一樣的模式:提高SQL查詢速度

|------------|-------------|------------|--------------| 
| cities |category_city| categories| companies | 
|------------|-------------|------------|--------------| 
|  id  | city_id |  id  |  id  | 
| name | category_id | name |subcategory_id| 
|   |    | parent_id | city_id | 
|   |    |   |...other cols | 
|____________|_____________|____________|______________| 

關係: 市同類別有->belongsToMany()

public function categories() 
{ 
    return $this->belongsToMany(Category::class); 
} 

類別有子類別:

public function subcategories() 
{ 
    return $this->hasMany(Category::class, 'parent_id', 'id'); 
} 

我從類別和城市篩選公司,因爲我需要當前的城市公司和我有一個全局範圍:

public function getCompanies($city_id) 
    { 
     return $this->companies()->whereHas('mainCity', function ($q) use ($city_id) { 
      $q->where('city_id', $city_id); 
     }); 
    } 

mainCity方法:

public function mainCity() 
{ 
    return $this->belongsTo(City::class, 'city_id'); 
} 

這裏是我的方法執行與AJAX請求查詢:

public function getPlaces(City $city, Category $subcategory, $north, $south, $east, $west) 
{ 
    $companies = $subcategory->companies() 
     ->withCount('comments') 
     ->companiesByBounds($north, $south, $east, $west) 
     ->paginate(8); 

    $markers = $subcategory->companies() 
     ->companiesByBounds($north, $south, $east, $west) 
     ->get(['lat', 'lng', 'slug', 'title']); 

    return response()->json(['companies' => $companies, 'markers' => $markers], 200, [], JSON_NUMERIC_CHECK); 
} 

和byByBounds示波器方法:

public function scopeCompaniesByBounds($query, $north, $south, $east, $west) 
{ 
    return $query->whereBetween('lat', [$south, $north]) 
     ->whereBetween('lng', [$west, $east]); 
} 

在公司我有~2m記錄。主要問題是查詢花費3.5秒。請幫助改善我的疑問。

下面是該查詢:

select count(*) as aggregate from `companies` where `companies`.`category_id` = '40' and `companies`.`category_id` is not null and `lat` between '53.68540097020851' and '53.749703253622705' and `lng` between '91.34262820463869' and '91.51600619536134'

+0

您是否嘗試過使用EXPLAIN/Visual Explain運行結果SQL來查看執行計劃? –

+0

不,我沒有。我怎樣才能做到這一點? – pwnz22

+0

我並不熟悉laravel,所以不知道如果http://stackoverflow.com/questions/18236294/how-do-i-get-the-query-builder-to-output-its-raw-sql- query-as-a-string將會爲你提供實際的SQL查詢。如果是這樣,那麼https://dev.mysql.com/doc/refman/5.7/en/explain.html展示瞭如何使用EXPLAIN,並且MySQL Workbench中的某處是Visual Explain。 –

回答

1

要提高,你需要在列latlng添加索引的速度。

CREATE INDEX idx_lat ON companies (lat); 

當列添加到條件時,索引用於查詢中。