【发布时间】:2018-02-27 02:34:30
【问题描述】:
我正在使用 Laravel 5.4
我有 3 个模型:Order、OrderLine 和 Product。
Order hasMany() OrderLines OrderLine hasOne() Product 通过 OrderLine 模型中的 product_id (我已经正确索引了这个,至少我认为!)
我的要求是检索产品属于某个品牌名称的所有订单和订单行。
这是我雄辩的问题。我知道查询有效,但是当放在大型数据集(大约 10,000 个订单,12,000 个订单行/产品)上时,它似乎无限运行
$orders = Order::whereBetween('order_date', [$this->start_date,$this->end_date])
->whereHas('lines', function ($q1){
$q1->whereHas('product', function ($q2){
$q2->where('brand', 'Brands>SanDisk');
});
})->with('lines')->with('lines.product')->get()->toArray();
通过 toSql() 方法调试时,这会产生以下 SQL。
select
*
from `orders`
where
`order_date` between ? and ?
and
exists (select * from `order_lines` where `orders`.`id` =`order_lines`.`order_id`
and
exists (select * from `products` where `order_lines`.`product_id` = `products`.`id` and `brand` = ?))
我创建表的 3 次迁移如下(为简单起见,我删除了除键之外的任何内容):
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
});
Schema::create('order_lines', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id');
$table->integer('order_id');
});
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
});
然后我添加了以下索引:
Schema::table('order_lines', function (Blueprint $table) {
$table->integer('product_id')->unsigned()->change();
$table->foreign('product_id')->references('id')->on('products');
});
EXPLAIN 语法结果如下:
1 PRIMARY orders ALL 91886 Using where
2 DEPENDENT SUBQUERY order_lines ALL 93166 Using where
3 DEPENDENT SUBQUERY products eq_ref PRIMARY PRIMARY 4 mymemory_main.order_lines.product_id 1 Using where
【问题讨论】:
-
优化问题应包括表订单、order_lines 和产品之外的 CREATE TABLE 结构。以及 EXPLAIN [query] 输出...
-
您可能希望使用
EXPLAIN语法检查mysql 控制台中的子查询,但我至少推荐order_lines.order_id和order_lines.product_id上的索引 -
能否请您说明您是如何索引这些表格的?
-
生成的 SQL 查询生成非常非常糟糕。生成的 SQL 将采用两个相关的子查询。相关子查询是性能最差的一种。
-
@RaymondNijland 我在问题正文中添加了 EXPLAIN 的结果
标签: php mysql sql laravel eloquent