shish пре 2 месеци
родитељ
комит
4041ee53b9
1 измењених фајлова са 33 додато и 21 уклоњено
  1. 33 21
      console/controllers/SaltController.php

+ 33 - 21
console/controllers/SaltController.php

@@ -21,18 +21,18 @@ use yii\console\ExitCode;
  * 用法:
  *   php yii salt/fill
  *   php yii salt/fill --dryRun=1
- *   php yii salt/fill --batchSize=50 --sleepMs=200
- *   php yii salt/fill --mode=pk --scanSize=2000
+ *   php yii salt/fill --batchSize=1000 --sleepMs=200
+ *   php yii salt/fill --mode=pk --scanSize=1000
  *   php yii salt/fill-ghs-order
  *   php yii salt/fill-cg
  */
 class SaltController extends Controller
 {
     /** @var int 每批处理条数 */
-    public $batchSize = 5000;
+    public $batchSize = 1000;
 
     /** @var int pk 模式下每次主键游标扫描行数 */
-    public $scanSize = 5000;
+    public $scanSize = 1000;
 
     /**
      * 扫描模式:
@@ -139,13 +139,13 @@ class SaltController extends Controller
     }
 
     /**
-     * 只查 salt='' 的记录,补完即停,不会扫描已有 salt 的上千万数据
+     * 只查 salt='' 的记录,从最大 id 向小 id 分批处理
      */
     private function fillByEmptySalt($label, $tableName)
     {
         $db = Yii::$app->db;
         $processed = 0;
-        $lastId = 0;
+        $lastId = null;
 
         while (true) {
             if ($this->limit > 0 && $processed >= $this->limit) {
@@ -153,18 +153,24 @@ class SaltController extends Controller
             }
 
             $batchLimit = $this->limit > 0 ? min($this->batchSize, $this->limit - $processed) : $this->batchSize;
-            $rows = $db->createCommand(
-                "SELECT id FROM {$tableName} WHERE salt = '' AND id > :lastId ORDER BY id ASC LIMIT {$batchLimit}"
-            )->bindValue(':lastId', $lastId)->queryColumn();
+            if ($lastId === null) {
+                $rows = $db->createCommand(
+                    "SELECT id FROM {$tableName} WHERE salt = '' ORDER BY id DESC LIMIT {$batchLimit}"
+                )->queryColumn();
+            } else {
+                $rows = $db->createCommand(
+                    "SELECT id FROM {$tableName} WHERE salt = '' AND id < :lastId ORDER BY id DESC LIMIT {$batchLimit}"
+                )->bindValue(':lastId', $lastId)->queryColumn();
+            }
 
             if (empty($rows)) {
                 break;
             }
 
             $processed += $this->updateIds($label, $tableName, $rows);
-            $lastId = (int)end($rows);
+            $lastId = (int)min($rows);
 
-            $this->stdout("{$label} 已处理 {$processed} 条,当前 id <= {$lastId}\n");
+            $this->stdout("{$label} 已处理 {$processed} 条,当前 id >= {$lastId}\n");
             $this->sleepBetweenBatch();
         }
 
@@ -172,33 +178,39 @@ class SaltController extends Controller
     }
 
     /**
-     * 按主键游标分段扫描,查询只走主键索引;适合 empty 模式执行计划不佳时使用
+     * 按主键从最大 id 向小 id 分段扫描;适合 empty 模式执行计划不佳时使用
      */
     private function fillByPrimaryKeyScan($label, $tableName)
     {
         $db = Yii::$app->db;
         $processed = 0;
-        $lastId = 0;
+        $lastId = null;
 
         while (true) {
             if ($this->limit > 0 && $processed >= $this->limit) {
                 break;
             }
 
-            $ids = $db->createCommand(
-                "SELECT id FROM {$tableName} WHERE id > :lastId ORDER BY id ASC LIMIT {$this->scanSize}"
-            )->bindValue(':lastId', $lastId)->queryColumn();
+            if ($lastId === null) {
+                $ids = $db->createCommand(
+                    "SELECT id FROM {$tableName} ORDER BY id DESC LIMIT {$this->scanSize}"
+                )->queryColumn();
+            } else {
+                $ids = $db->createCommand(
+                    "SELECT id FROM {$tableName} WHERE id < :lastId ORDER BY id DESC LIMIT {$this->scanSize}"
+                )->bindValue(':lastId', $lastId)->queryColumn();
+            }
 
             if (empty($ids)) {
                 break;
             }
 
-            $lastId = (int)end($ids);
-            $minId = (int)$ids[0];
-            $maxId = $lastId;
+            $lastId = (int)min($ids);
+            $minId = (int)min($ids);
+            $maxId = (int)max($ids);
 
             $emptyIds = $db->createCommand(
-                "SELECT id FROM {$tableName} WHERE id >= :minId AND id <= :maxId AND salt = '' ORDER BY id ASC"
+                "SELECT id FROM {$tableName} WHERE id >= :minId AND id <= :maxId AND salt = '' ORDER BY id DESC"
             )->bindValues([
                 ':minId' => $minId,
                 ':maxId' => $maxId,
@@ -211,7 +223,7 @@ class SaltController extends Controller
                 $processed += $this->updateIds($label, $tableName, $emptyIds);
             }
 
-            $this->stdout("{$label} 已处理 {$processed} 条,已扫描到 id={$lastId}\n");
+            $this->stdout("{$label} 已处理 {$processed} 条,已扫描到 id >= {$lastId}\n");
             $this->sleepBetweenBatch();
         }