Mysql 10月cms查询加载时间长
我正在尝试优化这个嵌套查询,它需要很长时间才能加载 基本思想是把属于一个部门的所有系列,中间属于属于多个部门和多个系列的产品。 表结构 部门**产品**系列 在这些模型中,关系的定义如下:部门模型Mysql 10月cms查询加载时间长,mysql,activerecord,octobercms,octobercms-plugins,Mysql,Activerecord,Octobercms,Octobercms Plugins,我正在尝试优化这个嵌套查询,它需要很长时间才能加载 基本思想是把属于一个部门的所有系列,中间属于属于多个部门和多个系列的产品。 表结构 部门**产品**系列 在这些模型中,关系的定义如下:部门模型 public $belongsToMany = [ 'products' => [ '\depcore\parts\Models\Product', 'table' => 'depcore_parts_products_departments'
public $belongsToMany = [
'products' => [
'\depcore\parts\Models\Product',
'table' => 'depcore_parts_products_departments',
],
// 'series' => [
// '\depcore\parts\Models\Series',
// 'table' => 'depcore_parts_products_series',
// ]
];
系列模型
public $hasMany = [
'products' => [
'\depcore\parts\Models\Product',
'table' => 'depcore_parts_products_departments',
]
];
产品模型
public $belongsToMany = [
'series' => [
'depcore\parts\Models\Series',
'table' => 'depcore_parts_products_series',
'order' => 'name',
],
'departments' => [
'depcore\parts\Models\Department',
'table' => 'depcore_parts_products_departments',
// 'order' => 'name'
]
];
在Department模型中,我创建了一个方法来检索属于Department的所有系列,这些系列在分析后导致了一些严重的性能问题
public function series (){
$seriesArray = array( );
$products = $this->products()->remember(100)->get();
foreach ($products as $product) {
$productSeries = $product->series()->remember(100)->get();
foreach ($productSeries as $series) {
if (!isset($seriesArray[$series->id]) and $series->published )
$seriesArray[$series->id] = $series;
}
}
return \Illuminate\Database\Eloquent\Collection::make($seriesArray);
}
我想这可以通过原始SQL或更好的活动记录实现来实现,但我在这两方面都有困难
我后来添加了memory()
方法,但没有结果。
目前网页的加载时间约为20秒。删除此代码时,会立即删除
任何建议都将不胜感激
从表结构来看,我想这将是为了获得所需结果而运行的适当SQL命令
SELECT DISTINCT series_id FROM depcore_parts_products_series WHERE product_id IN (SELECT DISTINCT product_id FROM depcore_parts_products_departments WHERE department_id = 3);
此查询仅在中间表上运行,并获得系列\u id
的正确结果(在phpmyadmin中)(以部门\u id=3为例)
使用Hardik Satasiya代码,我不得不更改几行,否则视图将不会显示任何序列,而只是空行
public function series (){
$sql = 'SELECT DISTINCT series_id FROM depcore_parts_products_series WHERE product_id IN (SELECT DISTINCT product_id FROM depcore_parts_products_departments WHERE department_id = :dep_id)';
$data = ['dep_id' => $this->id];
$query = \DB::select($sql, $data);
$data = $query;
$ids = array();
// I had to rewrite this pare and make it more inelegant still
// but the refresh method appeared to made it step out the execution cycle
foreach ($data as $key => $value) {
$ids[] = $value->series_id;
}
// in $data we are passing only id information
// so this records have only id, not db all attributes
// what ever you pass in $data will become model attributes if its in list
$collection = \depcore\parts\Models\Series::hydrate($ids);
return Series::published()->whereIn('id',$ids)->get();
}
这个街区是局部的
<div class="element-grid">
<h4 {% if hideChildren|length and departmentModel.id not in filters.departments %} class='inactive' {% endif %} ><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}">{{ departmentModel.name }}</a></h4>
{% if not hideChildren|length %}
<div class="list">
<div class="block left-block">
{% if departmentModel.getChildren|length %}
<ul class='departments'>
{% for child in departmentModel.getChildren %}
{% if child.published %}
<li><strong><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}&Filter[departments][]={{ child.id }}">{{ child.name }}</a></li></strong>
{% endif %}
{% endfor %}
</ul>
{% endif %}
<ul class="series">
{% for series in departmentModel.departmentSeries.series|slice(0,10) %}
<li><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}&{{ departmentModel.departmentSeries.childrenString }}&Filter[series][]={{ series.id }}">{{ series.name }}</a></li>
{% endfor %}
</ul>
</div>
<div class="block right-block">
<ul class="series series-right">
{% for series in departmentModel.departmentSeries.series|slice(10,length) %}
<li><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}&{{ departmentModel.departmentSeries.childrenString }}&Filter[series][]={{ series.id }}">{{ series.name }}</a></li>
{% endfor %}
</ul>
</div>
</div>
<img src="{{ departmentModel.image.file_name | media }}" alt="">
{% endif %}
</div>
您可以利用原始查询并将
获取的id
转换为您可以编写此代码的模型
$sql = 'SELECT DISTINCT series_id FROM depcore_parts_products_series WHERE product_id IN (SELECT DISTINCT product_id FROM depcore_parts_products_departments WHERE department_id = :dep_id');
$data = ['dep_id' => 2];
$query = \DB::select($sql, $data);
$data = $query;
foreach ($data as $model) {
$ids[] = $model->series_id;
}
$returnData = Series::whereIn('id',$ids)->get();
// dd($returnData);
return $returnData;
如果您发现任何困难,请评论
使现代化
我的部门型号
和页面代码部分
我正在使用您提供的html/partial
。它似乎在这里工作
确定所需的一些详细信息
系列型号
=>表depcore\u零件产品\u部门
是depcore\u零件产品\u系列
对吗?接下来,我们不能将部门id
添加到系列模型中,这样它就不会产生问题(不确定您的db架构),但我们可以使用它来避免参考链,系列可以指导点部门,而不是查看产品。我的观点是,您可能有其他用例,如果您有其他用例,并且上面的评论没有帮助,那么我们可以编写raw sql
,让我们知道,这样我们就可以准备raw sql
,我试图避免通过部门复制多对多关系。正如你所指出的,这些是中间表。现在,我希望保持结构不变,并使用原始sql从产品中获取系列ID。好的,我将尝试将您的问题复制到我的实例中,然后尝试为此构建原始查询我添加了一个原始sql语句,该语句可以正常工作-现在,我无法将其转换为精简活动记录实现。这很好,但我必须进行更改(第二次编辑),因为当使用刷新方法时,函数停止,并在视图中查看项目的位置。确定。添加。谢谢,您使用的是departmentModel.departmentSeries.series
是否正确?或者你不认为它应该是departmentModel.series
就像在我的开发机器departmentModel.series
中一样,如果它的departmentModel.departmentSeries.series
工作,那么请了解departmentSeries
的一些细节。很抱歉询问,但需要详细信息来解决问题:(是的,部门是在一个简单的树形结构中。不要担心询问我很高兴得到您的帮助,老实说,在回家的路上,我注意到我的编辑缺少您问到的功能:)好的,谢谢,我将添加这些内容并测试它,哈哈,你的问题是1英里长的办公室到家的距离……)
$sql = 'SELECT DISTINCT series_id FROM depcore_parts_products_series WHERE product_id IN (SELECT DISTINCT product_id FROM depcore_parts_products_departments WHERE department_id = :dep_id');
$data = ['dep_id' => 2];
$query = \DB::select($sql, $data);
$data = $query;
foreach ($data as $model) {
$ids[] = $model->series_id;
}
$returnData = Series::whereIn('id',$ids)->get();
// dd($returnData);
return $returnData;
use \October\Rain\Database\Traits\SimpleTree;
public $belongsTo = [
'parent' => ['HardikSatasiya\StackDemo\Models\Departments', 'key' => 'parent_id'],
];
public $hasMany = [
'children' => ['HardikSatasiya\StackDemo\Models\Departments', 'key' => 'parent_id'],
];
public function series() {
$sql = 'SELECT DISTINCT series_id FROM hardiksatasiya_stackdemo_product_series WHERE product_id IN (SELECT DISTINCT product_id FROM hardiksatasiya_stackdemo_department_product WHERE department_id = :dep_id)';
$data = ['dep_id' => $this->id];
$query = \DB::select($sql, $data);
$data = $query;
foreach ($data as $model) {
$ids[] = $model->series_id;
}
$returnData = Series::whereIn('id',$ids)->get();
// dd($returnData);
return $returnData;
}
public function scopeDepartmentSeries( $query ) {
$children = $query->getModel()->getChildren();
//dd($children);
if ( count( $children ) > 0 ) {
$seriesArray = array ( );
foreach ($children as $child) {
$childrenIds[] = 'Filter[departments][]='.$child->id;
foreach ($child->series ( ) as $series) {
if (!in_array($series->id,$seriesArray)) $seriesArray[] = $series->id;
// if (!array_key_exists($series->id,$seriesArray)) $seriesArray[$series->id] = $series->name;
}
} // endforeach children as child
$childrenString = implode( '&', $childrenIds );
return ["series" => Series::whereIn ( 'id',$seriesArray )->get ( ),
"childrenString" => $childrenString];
}
return ["series" => $query->getModel()->series( )];
}
function onInit() {
$departmentModel = \HardikSatasiya\StackDemo\Models\Departments::find(1);
//dd($departmentModel->getChildren());
$this['departmentModel'] = $departmentModel;
}