我使用的是MySQL,我的架构如下:
|------------|-------------|------------|--------------|
| 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);
}
并通过companiesByBounds范围方法:
public function scopeCompaniesByBounds($query, $north, $south, $east, $west)
{
return $query->whereBetween('lat', [$south, $north])
->whereBetween('lng', [$west, $east]);
}
在公司里我有大约200万条记录。主要问题是查询耗时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 :(得分:1)
要提高速度,您需要在列lat
和lng
上添加索引。
CREATE INDEX idx_lat ON companies (lat);
当列添加到条件时,索引将用于查询。