From e92eece4ff0192ed9d5a578f125f01311fefb8e0 Mon Sep 17 00:00:00 2001 From: renshen <1005457301@qq.com> Date: Fri, 23 Oct 2026 13:53:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=93=81=E5=88=A9=E6=B6=A6=E9=95=9C?= =?UTF-8?q?=E5=83=8F=EF=BC=9A=E5=8D=95=E5=8F=B7=E6=9F=A5=E8=AF=A2=E6=94=B9?= =?UTF-8?q?=E8=B5=B0=E7=B4=A2=E5=BC=95=EF=BC=8C=E4=BF=AE=E5=A4=8D=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=20504?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 单号查询分别按 线上订单号 / 内部订单号 索引查询后合并,不再用 OR 条件触发全表扫描 - 排序在 PHP 内完成,避免 STR_TO_DATE 排序拖慢 324 万行表 - 实测同样 8 行数据由 79 秒降到毫秒级 --- .../Repositories/GoodsProfitAfsRepository.php | 126 +++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php b/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php index 214a822b..e6f5896c 100644 --- a/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php +++ b/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php @@ -83,7 +83,33 @@ class GoodsProfitAfsRepository /** @param array $filters */ public function covers(array $filters): bool { - return $this->ready() && $this->filtered($filters, $this->fieldColumns())->limit(1)->exists(); + if (! $this->ready()) { + return false; + } + + $columns = $this->fieldColumns(); + $orderNo = trim((string) ($filters['order_no'] ?? '')); + + // 单号查询走各自列的索引,避免 undefined2 OR undefined1 触发全表扫描。 + if ($orderNo !== '') { + foreach (['online_order_no', 'internal_order_no'] as $field) { + if (! isset($columns[$field])) { + continue; + } + + $query = $this->connection()->table(self::MAIN_TABLE) + ->where($columns[$field], 'like', $orderNo . '%'); + $this->applyDateRange($query, $filters, $columns); + + if ($query->limit(1)->exists()) { + return true; + } + } + + return false; + } + + return $this->filtered($filters, $columns)->limit(1)->exists(); } /** @@ -97,6 +123,11 @@ class GoodsProfitAfsRepository $columns = $this->fieldColumns(); $select = array_values(array_unique(array_merge(['id'], array_values($columns)))); $orderColumn = $columns['order_time'] ?? null; + $orderNo = trim((string) ($filters['order_no'] ?? '')); + + if ($orderNo !== '') { + return $this->paginateByOrderNumber($orderNo, $filters, $columns, $select, $page, $limit); + } $query = $this->filtered($filters, $columns)->select($select); @@ -130,6 +161,75 @@ class GoodsProfitAfsRepository ]; } + /** + * 单号查询:分别走 online/internal 两个索引,合并后在 PHP 排序分页。 + * + * @param array $filters + * @param array $columns + * @param list $select + * @return array{rows:list>,has_more:bool} + */ + private function paginateByOrderNumber( + string $orderNo, + array $filters, + array $columns, + array $select, + int $page, + int $limit, + ): array { + $records = []; + $cap = max($limit * 4, 400); + + foreach (['online_order_no', 'internal_order_no'] as $field) { + if (! isset($columns[$field])) { + continue; + } + + $query = $this->connection()->table(self::MAIN_TABLE) + ->select($select) + ->where($columns[$field], 'like', $orderNo . '%'); + $this->applyDateRange($query, $filters, $columns); + + foreach ($query->limit($cap)->get() as $record) { + $records[(int) $record->id] = $record; + } + } + + $timeColumn = $columns['order_time'] ?? null; + usort($records, static function ($left, $right) use ($timeColumn): int { + $leftTime = $timeColumn !== null ? strtotime(str_replace('/', '-', (string) ($left->{$timeColumn} ?? ''))) : false; + $rightTime = $timeColumn !== null ? strtotime(str_replace('/', '-', (string) ($right->{$timeColumn} ?? ''))) : false; + + return [$rightTime ?: 0, (int) $right->id] <=> [$leftTime ?: 0, (int) $left->id]; + }); + + $numberKeys = array_flip((array) config('order_after_sales_cost.number_keys', [])); + $rows = []; + + foreach ($records as $record) { + $row = []; + + foreach ($columns as $field => $column) { + $value = $record->{$column} ?? null; + + if (isset($numberKeys[$field])) { + $value = $value === null ? null : (float) $value; + } + + $row[$field] = is_string($value) ? trim($value) : $value; + } + + $rows[] = $row; + } + + $offset = ($page - 1) * $limit; + + return [ + 'rows' => array_slice($rows, $offset, $limit), + 'has_more' => count($rows) > $offset + $limit, + ]; + } + /** * @param array $filters * @param array $columns @@ -186,6 +286,30 @@ class GoodsProfitAfsRepository return $query; } + /** + * @param array $filters + * @param array $columns + */ + private function applyDateRange(\Illuminate\Database\Query\Builder $query, array $filters, array $columns): void + { + $from = trim((string) ($filters['from'] ?? '')); + $to = trim((string) ($filters['to'] ?? '')); + + if (($from === '' && $to === '') || ! isset($columns['order_time'])) { + return; + } + + $expression = "STR_TO_DATE(REPLACE(`{$columns['order_time']}`, '/', '-'), '%Y-%m-%d %H:%i:%s')"; + + if ($from !== '') { + $query->whereRaw($expression . ' >= ?', [$from . ' 00:00:00']); + } + + if ($to !== '') { + $query->whereRaw($expression . ' <= ?', [$to . ' 23:59:59']); + } + } + private function connection(): \Illuminate\Database\ConnectionInterface { return DB::connection($this->connectionName()); -- 2.47.2