缓慢的简单 eloquent 查询
Slow simple eloquent queries
我是 laravel eloquent 的新手,我想知道加载时间是否通常只有五个条目
即使是一个简单的 select 所有查询都有大约 720 毫秒,特别是在第一张照片(模态)的编辑按钮上,数据在一秒钟后出现,这是显而易见的,
我正在使用 Livewire 我不知道是否影响太大
- 影响额外加载时间的主要问题是如何在仅计算服务总和的子 table 上访问(聚合),我在 html 上写了一个简单的计数
{{ $customer->services->count()}}
table 如您所见,在每一行上运行都是错误的,因为会增加额外的加载时间。
- 在 php 我做了类似的东西:
$sql = "SELECT name,vat,id";
$sql .= " ,(select sum(taskcharges) from charges where charges.customers_id=customers.id) as taskcharges_sum";
$sql .= " ,(select sum(payment) from charges where charges.customers_id=customers.id) as payment_sum";
$sql .= " ,(select sum(taskcharges-payment) from charges where charges.customers_id=customers.id) as balance_sum";
$sql .= " ,(select name WHERE customers.id=$id) ";
$sql .= " FROM customers ";
我想从客户那里获得对特定子(服务)列的访问权限,以实现像 max、sum、count 这样的函数 tables 绑定在模型上,所以我想避免额外的连接查询代码
另外,正如您在排序时看到的那样,“服务”不是客户 table 的列,因此他们无法识别客户 table 的列服务,如果我有类似“select count(services)作为 servicecount 那么我将能够将排序识别为 table 客户
的新列
上面你可以看到我的代码:
customers/show.blade.php:
<div class="container">
<p>Sort column:{{$selectedItems}}</p>
<p>Selected Direction:{{$action}}</p>
<!-- Button trigger modal -->
<button wire:click.prevent="addNew" type="button" class="btn btn-primary">
Add New User
</button>
<!-- button triger Modal -->
<div class="modal fade" id="form" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Insert</h5>
<button type="button" wire:click.prevent="close"class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
@livewire('customers.form')
</div>
</div>
</div>
</div>
<div class="modal fade" id="delete" tabindex="-1" role="dialog" aria-labelledby="delete" aria-hidden="true" wire:ignore>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="delete">Delete</h5>
<button type="button" wire:click.prevent="close" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<h3>Do you wish to continue?</h3>
</div>
<div class="modal-footer">
<button type="button" wire:click="close" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button wire:click="delete" class="btn btn-primary">Delete</button>
</div>
</div>
</div>
</div>
<h1 class="text-center">Customers {{count($customers)}}</h1>
<div>
<div class="w-full flex pb-10">
<div class="w-3/3 mx-1">
<input wire:model.debounce.300ms="search" type="text" class="form-control" placeholder="Search users...">
</div>
<div class="row mb-4">
<div class="col form-inline">
Per Page:
<select wire:model="perPage" class="form-control">
<option>5</option>
<option>10</option>
</select>
</div>
</div>
</div>
<table class="table-auto w-full mb-6">
<thead>
<tr>
<th wire:click="sortBy('id')" style="cursor: pointer;" class="px-4 py-2">ID
@include('layouts.partials.sort_icons',['field'=>'id'])
</th>
<th wire:click="sortBy('name')" style="cursor: pointer;" class="px-4 py-2">Name
@include('layouts.partials.sort_icons',['field'=>'id'])</th>
<th wire:click="sortBy('plate')" style="cursor: pointer;" class="px-4 py-2">Plate
@include('layouts.partials.sort_icons',['field'=>'id'])</th>
<th wire:click="sortBy('services')" style="cursor: pointer;" class="px-4 py-2">Services
@include('layouts.partials.sort_icons',['field'=>'services'])</th>
<th class="px-2 py-2">Action</th>
</tr>
</thead>
<tbody>
@foreach($customers as $customer)
<tr>
<td class="border px-4 py-2">{{ $customer->id }}</td>
<td class="border px-4 py-2">{{ $customer->name }}</td>
<td class="border px-4 py-2">{{ $customer->plate }}</td>
<td class="border px-4 py-2">{{ $customer->services->count()}}</td>
<td class="border px-2 py-2">
<button wire:click="selectItem({{$customer->id}},'update')" class="btn btn-info"><i class="fa fa-edit"></I></button></a>
<button wire:click="selectItem({{$customer->id}},'delete')" class="btn btn-danger"><i class="fa fa-trash"></I></button></a>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="paginate">{{$customers->links()}}</div>
</div>
</div>
customers/Show.php :
<?php
namespace App\Http\Livewire\Customers;
use App\Models\Customer;
use Livewire\Component;
use App\Page;
use Illuminate\Support\Str;
use App\Http\Livewire\Column;
use Livewire\WithPagination;
class Show extends Component
{
public $sortBy= 'name';
public $sortDirection = 'asc';
public $headers;
public $perPage ='5';
public $search;
public $action;
public $selectedItems;
public function sortBy($field){
if ($this->sortDirection =='asc'){
$this ->sortDirection ='desc';
}
else{
$this->sortDirection ='asc';
}
return $this ->sortBy = $field;
}
public function selectItem($itemId,$action){
$this->selectedItems=$itemId;
$this->action=$action;
if ($action=='delete'){
$this->dispatchBrowserEvent('show-deletemodal');
} else{
$this->emit('getcustomerID', $this->selectedItems);
$this->dispatchBrowserEvent('show-modal');
}
}
public function delete(){
Customer::destroy($this->selectedItems);
$this->dispatchBrowserEvent('hide-modal');
}
public function addNew()
{
$this->dispatchBrowserEvent('show-modal');
}
public function close()
{
$this->dispatchBrowserEvent('hide-modal');
}
protected $listeners = [
'deleteconfirmed'=>'$selectedItems',
'refreshParent'=>'$refresh'
];
public function render()
{
$customers = Customer::query()
->search($this->search)
->orderBy($this->sortBy,$this->sortDirection)
->paginate($this->perPage);
return view('livewire.customers.show',['customers'=>$customers
])
->extends('admin.dashboard')
->section('content');
}
}
customers/form.php :
<?php
namespace App\Http\Livewire\Customers;
use App\Models\Customer;
use Livewire\Component;
class Form extends Component
{
public $name ='';
public $plate = '';
public $customerId ;
protected $listeners = [
'getcustomerID'
];
protected function rules() {
return [
'name' => 'required',
'plate' => ['required', 'regex:/[A-Z]{3}\d{4}$/','unique:customers,plate,' . $this->customerId],
];
}
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function getcustomerID($customerId){
$this->customerId=$customerId;
$customer= customer::find ($this->customerId);
$this->name=$customer->name;
$this->plate= $customer->plate;
}
public function save()
{
$this->validate();
$data = [
'name' => $this->name,
'plate' => $this->plate,
];
if ($this->customerId){
customer::find ($this->customerId)->update($data);
session()->flash('message', 'User successfully updated.');
} else{
customer::create($data);
}
$this->emit('refreshParent');
$this->dispatchBrowserEvent('hide-modal');
$this ->ClearVars();
}
public function ClearVars(){
$this->name=null;
$this->plate=null;
}
public function render()
{
return view('livewire.customers.form');
}
}
Models/Customer.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
use HasFactory;
protected $fillable = [
'name',
'plate'
];
public function services()
{
return $this->hasMany(Service::class);
}
public function parts()
{
return $this->hasMany(Part::class, 'customer_id');
}
public function scopeSearch($query , $val){
return $query
->where('name','like','%'.$val.'%')
->Orwhere('plate','like','%'.$val.'%');
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Models/Services.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Service extends Model
{
protected $fillable = [
'service_type',
'km',
];
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function parts()
{
return $this->hasMany(part::class);
}
}
原来如此简单.. 只需在查询上方添加 ->withCount('services')
还有那个奇怪的延迟
更新:
响应慢的问题是试图从远程 sql 服务器检索数据,我切换到本地并且我只有不到 100 毫秒!
我是 laravel eloquent 的新手,我想知道加载时间是否通常只有五个条目
即使是一个简单的 select 所有查询都有大约 720 毫秒,特别是在第一张照片(模态)的编辑按钮上,数据在一秒钟后出现,这是显而易见的, 我正在使用 Livewire 我不知道是否影响太大
- 影响额外加载时间的主要问题是如何在仅计算服务总和的子 table 上访问(聚合),我在 html 上写了一个简单的计数
{{ $customer->services->count()}}
table 如您所见,在每一行上运行都是错误的,因为会增加额外的加载时间。 - 在 php 我做了类似的东西:
$sql = "SELECT name,vat,id";
$sql .= " ,(select sum(taskcharges) from charges where charges.customers_id=customers.id) as taskcharges_sum";
$sql .= " ,(select sum(payment) from charges where charges.customers_id=customers.id) as payment_sum";
$sql .= " ,(select sum(taskcharges-payment) from charges where charges.customers_id=customers.id) as balance_sum";
$sql .= " ,(select name WHERE customers.id=$id) ";
$sql .= " FROM customers ";
我想从客户那里获得对特定子(服务)列的访问权限,以实现像 max、sum、count 这样的函数 tables 绑定在模型上,所以我想避免额外的连接查询代码 另外,正如您在排序时看到的那样,“服务”不是客户 table 的列,因此他们无法识别客户 table 的列服务,如果我有类似“select count(services)作为 servicecount 那么我将能够将排序识别为 table 客户
的新列上面你可以看到我的代码:
customers/show.blade.php:
<div class="container">
<p>Sort column:{{$selectedItems}}</p>
<p>Selected Direction:{{$action}}</p>
<!-- Button trigger modal -->
<button wire:click.prevent="addNew" type="button" class="btn btn-primary">
Add New User
</button>
<!-- button triger Modal -->
<div class="modal fade" id="form" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Insert</h5>
<button type="button" wire:click.prevent="close"class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
@livewire('customers.form')
</div>
</div>
</div>
</div>
<div class="modal fade" id="delete" tabindex="-1" role="dialog" aria-labelledby="delete" aria-hidden="true" wire:ignore>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="delete">Delete</h5>
<button type="button" wire:click.prevent="close" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<h3>Do you wish to continue?</h3>
</div>
<div class="modal-footer">
<button type="button" wire:click="close" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button wire:click="delete" class="btn btn-primary">Delete</button>
</div>
</div>
</div>
</div>
<h1 class="text-center">Customers {{count($customers)}}</h1>
<div>
<div class="w-full flex pb-10">
<div class="w-3/3 mx-1">
<input wire:model.debounce.300ms="search" type="text" class="form-control" placeholder="Search users...">
</div>
<div class="row mb-4">
<div class="col form-inline">
Per Page:
<select wire:model="perPage" class="form-control">
<option>5</option>
<option>10</option>
</select>
</div>
</div>
</div>
<table class="table-auto w-full mb-6">
<thead>
<tr>
<th wire:click="sortBy('id')" style="cursor: pointer;" class="px-4 py-2">ID
@include('layouts.partials.sort_icons',['field'=>'id'])
</th>
<th wire:click="sortBy('name')" style="cursor: pointer;" class="px-4 py-2">Name
@include('layouts.partials.sort_icons',['field'=>'id'])</th>
<th wire:click="sortBy('plate')" style="cursor: pointer;" class="px-4 py-2">Plate
@include('layouts.partials.sort_icons',['field'=>'id'])</th>
<th wire:click="sortBy('services')" style="cursor: pointer;" class="px-4 py-2">Services
@include('layouts.partials.sort_icons',['field'=>'services'])</th>
<th class="px-2 py-2">Action</th>
</tr>
</thead>
<tbody>
@foreach($customers as $customer)
<tr>
<td class="border px-4 py-2">{{ $customer->id }}</td>
<td class="border px-4 py-2">{{ $customer->name }}</td>
<td class="border px-4 py-2">{{ $customer->plate }}</td>
<td class="border px-4 py-2">{{ $customer->services->count()}}</td>
<td class="border px-2 py-2">
<button wire:click="selectItem({{$customer->id}},'update')" class="btn btn-info"><i class="fa fa-edit"></I></button></a>
<button wire:click="selectItem({{$customer->id}},'delete')" class="btn btn-danger"><i class="fa fa-trash"></I></button></a>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="paginate">{{$customers->links()}}</div>
</div>
</div>
customers/Show.php :
<?php
namespace App\Http\Livewire\Customers;
use App\Models\Customer;
use Livewire\Component;
use App\Page;
use Illuminate\Support\Str;
use App\Http\Livewire\Column;
use Livewire\WithPagination;
class Show extends Component
{
public $sortBy= 'name';
public $sortDirection = 'asc';
public $headers;
public $perPage ='5';
public $search;
public $action;
public $selectedItems;
public function sortBy($field){
if ($this->sortDirection =='asc'){
$this ->sortDirection ='desc';
}
else{
$this->sortDirection ='asc';
}
return $this ->sortBy = $field;
}
public function selectItem($itemId,$action){
$this->selectedItems=$itemId;
$this->action=$action;
if ($action=='delete'){
$this->dispatchBrowserEvent('show-deletemodal');
} else{
$this->emit('getcustomerID', $this->selectedItems);
$this->dispatchBrowserEvent('show-modal');
}
}
public function delete(){
Customer::destroy($this->selectedItems);
$this->dispatchBrowserEvent('hide-modal');
}
public function addNew()
{
$this->dispatchBrowserEvent('show-modal');
}
public function close()
{
$this->dispatchBrowserEvent('hide-modal');
}
protected $listeners = [
'deleteconfirmed'=>'$selectedItems',
'refreshParent'=>'$refresh'
];
public function render()
{
$customers = Customer::query()
->search($this->search)
->orderBy($this->sortBy,$this->sortDirection)
->paginate($this->perPage);
return view('livewire.customers.show',['customers'=>$customers
])
->extends('admin.dashboard')
->section('content');
}
}
customers/form.php :
<?php
namespace App\Http\Livewire\Customers;
use App\Models\Customer;
use Livewire\Component;
class Form extends Component
{
public $name ='';
public $plate = '';
public $customerId ;
protected $listeners = [
'getcustomerID'
];
protected function rules() {
return [
'name' => 'required',
'plate' => ['required', 'regex:/[A-Z]{3}\d{4}$/','unique:customers,plate,' . $this->customerId],
];
}
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function getcustomerID($customerId){
$this->customerId=$customerId;
$customer= customer::find ($this->customerId);
$this->name=$customer->name;
$this->plate= $customer->plate;
}
public function save()
{
$this->validate();
$data = [
'name' => $this->name,
'plate' => $this->plate,
];
if ($this->customerId){
customer::find ($this->customerId)->update($data);
session()->flash('message', 'User successfully updated.');
} else{
customer::create($data);
}
$this->emit('refreshParent');
$this->dispatchBrowserEvent('hide-modal');
$this ->ClearVars();
}
public function ClearVars(){
$this->name=null;
$this->plate=null;
}
public function render()
{
return view('livewire.customers.form');
}
}
Models/Customer.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
use HasFactory;
protected $fillable = [
'name',
'plate'
];
public function services()
{
return $this->hasMany(Service::class);
}
public function parts()
{
return $this->hasMany(Part::class, 'customer_id');
}
public function scopeSearch($query , $val){
return $query
->where('name','like','%'.$val.'%')
->Orwhere('plate','like','%'.$val.'%');
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Models/Services.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Service extends Model
{
protected $fillable = [
'service_type',
'km',
];
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function parts()
{
return $this->hasMany(part::class);
}
}
原来如此简单.. 只需在查询上方添加 ->withCount('services')
还有那个奇怪的延迟
更新: 响应慢的问题是试图从远程 sql 服务器检索数据,我切换到本地并且我只有不到 100 毫秒!