如何在Laravel中优化构建关联关系并高效统计数据?
优化点击量统计性能并建立关联关系
一、建立模型关联
在Country模型中定义与Hit的一对多关联,直接绑定type = 'cities'的过滤条件,后续查询更简洁:
// app/Models/Country.php public function cityHits() { return $this->hasMany(Hit::class)->where('type', 'cities'); }
二、核心性能优化方案
1. 合并查询减少数据库请求
原代码分两次查询Country和Hit,改用关联查询合并为一次数据库交互:
$country = Country::where('key', strip_tags($key))->first(); $count = $country ? $country->cityHits()->distinct('type_id')->count() : 0;
2. 添加联合索引(最关键优化)
慢查询的核心原因通常是缺少合适索引,给hits表创建覆盖查询条件的联合索引:
CREATE INDEX idx_hits_type_country_typeid ON hits (type, country_id, type_id);
该索引覆盖了WHERE过滤的type、country_id,以及DISTINCT用到的type_id,数据库可直接通过索引完成统计,无需扫描全表。
3. 简化不必要的处理
如果country表的key字段入库时已做过清洗(无HTML标签),直接移除strip_tags减少PHP层面的开销:
$country = Country::where('key', $key)->first();
4. 原生SQL进一步提升效率
若ORM封装仍有性能损耗,可直接使用原生联合查询:
$count = DB::selectOne(" SELECT COUNT(DISTINCT type_id) AS count FROM hits JOIN countries ON hits.country_id = countries.id WHERE countries.key = ? AND hits.type = 'cities' ", [strip_tags($key)])->count;
三、额外优化建议
- 缓存非实时数据:若统计结果不需要实时更新,用Redis缓存统计值,降低数据库查询频率:
$cacheKey = "country_city_hits_{$key}"; $count = Cache::remember($cacheKey, 300, function () use ($key) { return Country::where('key', strip_tags($key)) ->first() ->cityHits() ->distinct('type_id') ->count(); });
- 数据归档/分表:若
hits表数据量极大,可按时间分表或归档历史数据,减少单表数据规模。
内容的提问来源于stack exchange,提问作者micky
相关产品推荐
相关产品推荐

