Skip to content

Commit 70fcb94

Browse files
Use batch updates for test table migration (#2442)
#2148 introduced a large migration which has proven to be problematic for CDash instances with many tests. This PR breaks the single large update statement into a batched update process where updates are performed in groups of 5000 rows at a time. Co-authored-by: Zack Galbreath <[email protected]>
1 parent 1ff7504 commit 70fcb94

File tree

1 file changed

+56
-13
lines changed

1 file changed

+56
-13
lines changed

database/migrations/2024_04_17_183212_remove_test_table.php

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,57 @@ public function up(): void
1919
->nullable(); // Temporarily make the column nullable
2020
});
2121

22-
if (config('database.default') === 'pgsql') {
23-
DB::update('
24-
UPDATE build2test
25-
SET testname = test.name
26-
FROM test
27-
WHERE test.id = build2test.testid
28-
');
29-
} else {
30-
DB::update('
31-
UPDATE build2test, test
32-
SET build2test.testname = test.name
33-
WHERE test.id = build2test.testid
34-
');
22+
$this->print('Migrate testname to build2test table');
23+
$done = false;
24+
$num_done = 0;
25+
$next_report = 10;
26+
$start = DB::table('build2test')->min('id');
27+
$max = DB::table('build2test')->max('id');
28+
$total = $max - $start;
29+
if ($total < 1) {
30+
if (DB::table('build2test')->count() > 0) {
31+
$error_msg = "Could not determine min & max id for build2test table.\n";
32+
$error_msg .= "Manually set \$start and \$max and rerun the migration\n";
33+
throw new Exception($error_msg);
34+
} else {
35+
$done = true;
36+
}
37+
}
38+
while (!$done) {
39+
$end = $start + 4999;
40+
if (config('database.default') === 'pgsql') {
41+
DB::update("
42+
UPDATE build2test
43+
SET testname = test.name
44+
FROM test
45+
WHERE build2test.testid = test.id AND
46+
build2test.id BETWEEN $start AND $end");
47+
} else {
48+
DB::update("
49+
UPDATE build2test
50+
INNER JOIN test ON build2test.testid = test.id
51+
SET build2test.testname = test.name
52+
WHERE build2test.id BETWEEN $start AND $end");
53+
}
54+
$num_done += 5000;
55+
if ($end >= $max) {
56+
$done = true;
57+
} else {
58+
usleep(1);
59+
$start += 5000;
60+
// Calculate percentage inserted.
61+
62+
// Just here to make PHPStan happy. This case should never happen.
63+
if ($total === 0) {
64+
continue;
65+
}
66+
67+
$percent = round(($num_done / $total) * 100, -1);
68+
if ($percent > $next_report) {
69+
$this->print("{$percent}%");
70+
$next_report = $percent + 10;
71+
}
72+
}
3573
}
3674

3775
$num_b2t_rows_deleted = DB::delete('DELETE FROM build2test WHERE testname IS NULL');
@@ -79,6 +117,11 @@ public function up(): void
79117
}
80118
}
81119

120+
public function print(string $msg): void
121+
{
122+
echo date('[Y-m-d H:i:s] ') . $msg . PHP_EOL;
123+
}
124+
82125
/**
83126
* Reverse the migrations.
84127
*/

0 commit comments

Comments
 (0)