Eloquent hasOne和一个大表,在查询中没有限制

时间:2018-04-19 09:24:34

标签: mysql sql laravel performance eloquent

我有一张表:

CREATE TABLE `weathers` (
  `id` int(10) UNSIGNED NOT NULL,
  `id_district` int(10) UNSIGNED DEFAULT NULL,
  `id_county` int(10) UNSIGNED DEFAULT NULL,
  `id_freg` int(10) UNSIGNED DEFAULT NULL,
  `temp` decimal(6,2) DEFAULT NULL,
  `temp_max` decimal(6,2) DEFAULT NULL,
  `temp_min` decimal(6,2) DEFAULT NULL,
  `pressure` decimal(9,3) DEFAULT NULL,
  `humidity` tinyint(4) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

ALTER TABLE `weathers`
  ADD PRIMARY KEY (`id`),
  ADD KEY `current_weathers_id_district_index` (`id_district`),
  ADD KEY `current_weathers_id_county_index` (`id_county`),
  ADD KEY `current_weathers_id_freg_index` (`id_freg`);

ALTER TABLE `weathers`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;

此表有超过4M的行,我可以为区,县或freg(小本地)选择当前天气(最后插入的行)。

执行以下查询,例如:

select * from `weathers` where `weathers`.`id_county` in (?) order by `id` desc [197] 

County模型:

中的关系应用
public function current_weather() {
    return $this->hasOne(\App\Weather::class, 'id_county')->orderBy('id', 'DESC');
}

所有行都属于county,district或freg,其中两行的所有行都为null。例如:如果我正在寻找id_county = 197NULLid_districtid_freg的行。

主要的问题是hasOne在查询本身中应该限制为1,这应该是隐含的,还是我错了?

由于它不是这样的,我遇到了重大的性能问题,例如10个县进行10次以上的查询是因为关系hasOne不是这样的限制查询本身的结果。

注意:使用Laravel 5.5

1 个答案:

答案 0 :(得分:2)

hasOne()不是在此上下文中使用的正确关系。要获得某个县的天气,您需要定义hasMany()关系以获取该郡的所有天气。然后,您还需要在天气模型上定义范围,以便仅获取最新条目。

public function scopeCurrent($query) {
    return $query->orderBy('id', 'desc')->limit(1);
}

当你想要得到一个县的当前天气时,你会这样:

$currentWeather = $county->weather()->current()->first();

设计关系时的重要区别在于,关系是县与天气之间的关系。不在县和天气表的单个项目之间。