use EXPLAIN and workout where you need to add indexes. For instance, it would be pretty silly if market_id is not indexed
I would also query by the column formats not convert them to unix timestamp
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
laravel : 10
mysql 8.0
have 2 server mysql
1 for write 2 core , 4 Ram , 250GB NVME
1 for read 2 core , 4 Ram , 250GB NVME
in transactions table : 6 million record They are increasing on a daily basis
$table->boolean('is_maker')->index()->default(false);
$table->integer('market_id')->index();
$table->index(['created_at']);
database.php
'read' => [
'host' => [
env('DB_HOST_READ', env('DB_HOST', '127.0.0.1'))
],
],
'write' => [
'host' => [
env('DB_HOST', '127.0.0.1'),
],
],
'sticky' => true,
query This fetches data for the tradingView (datafeed api)
Execution time: 18 seconds
public function getCandles($market)
{
$from = intval(request()->get('from'));
$to = intval(request()->get('to'));
$limitGet = request()->get('countback', 200) > 330 ? 330 : request()->get('countback', 200);
$rangeInSeconds = $from - $to;
if ($rangeInSeconds > 3000000) {
$to = $from;
}
$resolution = request()->get('resolution', '60');
$interval = MARKET_RESOLUTION_ASSOC[$resolution] ?? false;
if (!$interval) {
return false;
}
// low price, high price, open price, close price, volume, timestamp sameh
$transaction = Transaction::query();
if ($market) {
$transaction->where('market_id', $market->id);
}
$transaction->maker()->whereRaw('UNIX_TIMESTAMP(created_at) > ?', $from)
->whereRaw('UNIX_TIMESTAMP(created_at) < ?', $to);
$transaction
->selectRaw("DATE_FORMAT(MIN(created_at), '%d-%m-%Y %H:%i:00') as date2")
->selectRaw('FROM_UNIXTIME(FLOOR((UNIX_TIMESTAMP(created_at))/ ? ) * ?) AS date', [$interval, $interval])
->selectRaw('SUM(quote_currency) as volume')
->selectRaw('MAX(price) as high')
->selectRaw('MIN(price) as low')
->selectRaw("SUBSTRING_INDEX(MAX(CONCAT(created_at, '_', price)), '_', -1) as close")
->selectRaw("SUBSTRING_INDEX(MIN(CONCAT(created_at, '_', price)), '_', -1) as open");
$transaction
->limit($limitGet)
->groupByRaw('date')
->orderByRaw('date ASC');
return $transaction->get();
}
Are there any suggestions to improve the time, whatever these suggestions are, such as modifying the databases, transferring NoSql, or improving the code? Any idea that helps me improve the execution time?
so if your records are efficiently partitioned by date, and you have indexes on maker and market_id then the next candidates are the sum, min and max functions. Your query has to consider 250K rows and has no choice but to sum them order and select min+max
I would start by comparing the query time without these and then selectively adding them back in
I still worry about your dates. I don't know why you need to run functions against created_at and would strongly recommend passing the query the correctly formatted dates/times so that created_at index can be used directly
Please or to participate in this conversation.