Skip to content

Commit bcedb93

Browse files
committed
优化
1 parent ffc1a6f commit bcedb93

File tree

2 files changed

+180
-43
lines changed

2 files changed

+180
-43
lines changed

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77
ThinkPHP 5
88

99
```php
10-
$shardingQuery = new ShardingQuery(
11-
'think\Db::query',
12-
[
10+
$shardingQuery = new ShardingQuery([
11+
'callback' => 'think\Db::query',
12+
'table' => [
1313
'order',
14-
'order_history',
14+
'order_201805',
15+
'order_201804',
1516
],
16-
'SELECT * FROM {table}',
17-
10,
18-
0
19-
);
17+
'field' => '*',
18+
'where' => 'member_id = 10001',
19+
'offset' => 32,
20+
'limit' => 3,
21+
]);
2022
$res = $shardingQuery->select();
21-
var_dump($res);
2223
```

ShardingQuery.php

Lines changed: 170 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/**
44
* 根据时间同构分表的查询类
5+
* @package app\common\library
56
* @author LIUJIAN <coder.keda@gmail.com>
67
*/
78
class ShardingQuery
@@ -19,13 +20,25 @@ class ShardingQuery
1920
* 根据顺序查询
2021
* @var array
2122
*/
22-
public $tables;
23+
public $table;
2324

2425
/**
25-
* 查询语句
26+
* 字段
2627
* @var string
2728
*/
28-
public $sql;
29+
public $field;
30+
31+
/**
32+
* 条件
33+
* @var string
34+
*/
35+
public $where;
36+
37+
/**
38+
* 排序
39+
* @var string
40+
*/
41+
public $order;
2942

3043
/**
3144
* 限制数
@@ -40,24 +53,63 @@ class ShardingQuery
4053
public $offset;
4154

4255
/**
43-
* 数据表的通配符
44-
* @var string
56+
* 统计
57+
* @var array
4558
*/
46-
protected static $tableSymbol = '{table}';
59+
protected $stats;
4760

4861
/**
49-
* ShardingSelect constructor.
50-
* @param array $tables
51-
* @param callable $callback
52-
* @param string $sql
62+
* ShardingQuery constructor.
63+
* @param array $config
5364
*/
54-
public function __construct(callable $callback, array $tables, string $sql, int $limit, int $offset)
65+
public function __construct(array $config)
5566
{
56-
$this->callback = $callback;
57-
$this->tables = $tables;
58-
$this->sql = $sql;
59-
$this->limit = $limit;
60-
$this->offset = $offset;
67+
foreach ($config as $key => $value) {
68+
switch ($key) {
69+
case 'callback':
70+
if (!is_callable($value)) {
71+
throw new \RuntimeException("'callback' is not a callable type.");
72+
}
73+
$this->$key = $value;
74+
break;
75+
case 'table':
76+
if (!is_array($value)) {
77+
throw new \RuntimeException("'table' is not a array type.");
78+
}
79+
$this->$key = $value;
80+
break;
81+
case 'field':
82+
if (!is_string($value)) {
83+
throw new \RuntimeException("'field' is not a string type.");
84+
}
85+
$this->$key = $value;
86+
break;
87+
case 'where':
88+
if (!is_string($value)) {
89+
throw new \RuntimeException("'where' is not a string type.");
90+
}
91+
$this->$key = $value;
92+
break;
93+
case 'order':
94+
if (!is_string($value)) {
95+
throw new \RuntimeException("'order' is not a string type.");
96+
}
97+
$this->$key = $value;
98+
break;
99+
case 'limit':
100+
if (!is_int($value)) {
101+
throw new \RuntimeException("'limit' is not a int type.");
102+
}
103+
$this->$key = $value;
104+
break;
105+
case 'offset':
106+
if (!is_int($value)) {
107+
throw new \RuntimeException("'offset' is not a int type.");
108+
}
109+
$this->$key = $value;
110+
break;
111+
}
112+
}
61113
}
62114

63115
/**
@@ -66,28 +118,112 @@ public function __construct(callable $callback, array $tables, string $sql, int
66118
*/
67119
public function select()
68120
{
69-
$data = [];
70-
foreach ($this->tables as $num => $table) {
71-
if (count($data) < $this->limit) {
72-
$limit = $this->limit;
73-
$offset = $this->offset;
74-
if ($num > 0) {
75-
$limit = $this->limit - count($data);
76-
$offset = 0;
77-
}
78-
$sql = "{$this->sql} LIMIT {$limit} OFFSET {$offset}";
79-
$sql = str_replace(static::$tableSymbol, $table, $sql);
80-
$result = call_user_func($this->callback, $sql);
81-
if (empty($result)) {
82-
return $data;
83-
}
84-
$data = array_merge($data, $result);
121+
$this->stats = $this->stats($this->table);
122+
$range = $this->range($this->stats);
123+
$data = [];
124+
foreach ($range as $tableName => $item) {
125+
$sql = "SELECT {$this->field} FROM `{$tableName}`";
126+
if (!empty($this->where)) {
127+
$sql .= " WHERE {$this->where}";
85128
}
86-
if (count($data) >= $this->limit) {
87-
return $data;
129+
if (!empty($this->order)) {
130+
$sql .= " ORDER BY {$this->order}";
88131
}
132+
$sql = "{$sql} LIMIT {$item['limit']} OFFSET {$item['offset']}";
133+
$result = call_user_func($this->callback, $sql);
134+
$data = array_merge($data, $result);
89135
}
90136
return $data;
91137
}
92138

139+
/**
140+
* 获取表的统计信息
141+
* @param $table
142+
* @return array
143+
*/
144+
protected function stats($table)
145+
{
146+
$end = 0;
147+
$stats = [];
148+
foreach ($table as $num => $tableName) {
149+
$sql = "SELECT COUNT(*) FROM `{$tableName}`";
150+
if (!empty($this->where)) {
151+
$sql .= " WHERE {$this->where}";
152+
}
153+
$result = call_user_func($this->callback, $sql);
154+
$first = array_pop($result);
155+
$count = array_pop($first);
156+
$start = $end;
157+
$end += $count;
158+
$stats[$tableName] = [
159+
'start' => $start,
160+
'end' => $end,
161+
];
162+
}
163+
return $stats;
164+
}
165+
166+
/**
167+
* 获取要提取的表数据范围
168+
* @param $stats
169+
* @return array
170+
*/
171+
protected function range($stats)
172+
{
173+
$limit = $this->limit;
174+
$offset = $this->offset;
175+
$start = $offset;
176+
$end = $offset + $limit;
177+
$tables = [];
178+
foreach ($stats as $table => $item) {
179+
$before = $item['start'] <= $start && $item['end'] >= $start ? true : false;
180+
$center = $item['start'] > $start && $item['end'] < $end ? true : false;
181+
$after = $item['start'] <= $end && $item['end'] >= $end ? true : false;
182+
if ($before && $after) {
183+
$tables[$table] = [
184+
'offset' => $start - $item['start'],
185+
'limit' => $end - $start,
186+
];
187+
continue;
188+
}
189+
if ($before) {
190+
$tables[$table] = [
191+
'offset' => $start - $item['start'],
192+
'limit' => $item['end'] - $start,
193+
];
194+
if ($tables[$table]['limit'] == 0) {
195+
unset($tables[$table]);
196+
}
197+
continue;
198+
}
199+
if ($after) {
200+
$tables[$table] = [
201+
'offset' => 0,
202+
'limit' => $end - $item['start'],
203+
];
204+
continue;
205+
}
206+
if ($center) {
207+
$tables[$table] = [
208+
'offset' => 0,
209+
'limit' => $item['end'] - $item['start'],
210+
];
211+
continue;
212+
}
213+
}
214+
return $tables;
215+
}
216+
217+
/**
218+
* 获取数据总数
219+
* @return int
220+
*/
221+
public function count()
222+
{
223+
$stats = $this->stats;
224+
$last = array_pop($stats);
225+
$number = array_pop($last);
226+
return $number ?: 0;
227+
}
228+
93229
}

0 commit comments

Comments
 (0)