Faster initial database creation (#12297)

* Faster initial database creation
Add db dumps to improve initial db migration
On my test system 13s -> 7s, a 46% reduction.
Should help out a lot on systems like RPi

* lnms schema:dump command

--snapshots saves db snapshots, otherwise it saves the yaml

* fix style

* fix timezones...

* not working with in-memory db yet
remove build.sql
This commit is contained in:
Tony Murray
2020-11-05 18:19:15 -06:00
committed by GitHub
parent 03c950af8c
commit 25722bbbd5
10 changed files with 5663 additions and 196 deletions

View File

@@ -2186,83 +2186,6 @@ function cache_peeringdb()
}
}
/**
* Dump the database schema to an array.
* The top level will be a list of tables
* Each table contains the keys Columns and Indexes.
*
* Each entry in the Columns array contains these keys: Field, Type, Null, Default, Extra
* Each entry in the Indexes array contains these keys: Name, Columns(array), Unique
*
* @param string $connection use a specific connection
* @return array
*/
function dump_db_schema($connection = null)
{
$output = [];
$db_name = DB::connection($connection)->getDatabaseName();
foreach (DB::connection($connection)->select(DB::raw("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = '$db_name' ORDER BY TABLE_NAME;")) as $table) {
$table = $table->TABLE_NAME;
foreach (DB::connection($connection)->select(DB::raw("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '$db_name' AND TABLE_NAME='$table'")) as $data) {
$def = [
'Field' => $data->COLUMN_NAME,
'Type' => preg_replace('/int\([0-9]+\)/', 'int', $data->COLUMN_TYPE),
'Null' => $data->IS_NULLABLE === 'YES',
'Extra' => str_replace('current_timestamp()', 'CURRENT_TIMESTAMP', $data->EXTRA),
];
if (isset($data->COLUMN_DEFAULT) && $data->COLUMN_DEFAULT != 'NULL') {
$default = trim($data->COLUMN_DEFAULT, "'");
$def['Default'] = str_replace('current_timestamp()', 'CURRENT_TIMESTAMP', $default);
}
// MySQL 8 fix, remove DEFAULT_GENERATED from timestamp extra columns
if ($def['Type'] == 'timestamp') {
$def['Extra'] = preg_replace('/DEFAULT_GENERATED[ ]*/', '', $def['Extra']);
}
$output[$table]['Columns'][] = $def;
}
$keys = DB::connection($connection)->select(DB::raw("SHOW INDEX FROM `$table`"));
usort($keys, function ($a, $b) {
return $a->Key_name <=> $b->Key_name;
});
foreach ($keys as $key) {
$key_name = $key->Key_name;
if (isset($output[$table]['Indexes'][$key_name])) {
$output[$table]['Indexes'][$key_name]['Columns'][] = $key->Column_name;
} else {
$output[$table]['Indexes'][$key_name] = [
'Name' => $key->Key_name,
'Columns' => [$key->Column_name],
'Unique' => ! $key->Non_unique,
'Type' => $key->Index_type,
];
}
}
$create = DB::connection($connection)->select(DB::raw("SHOW CREATE TABLE `$table`"))[0];
if (isset($create->{'Create Table'})) {
$constraint_regex = '/CONSTRAINT `(?<name>[A-Za-z_0-9]+)` FOREIGN KEY \(`(?<foreign_key>[A-Za-z_0-9]+)`\) REFERENCES `(?<table>[A-Za-z_0-9]+)` \(`(?<key>[A-Za-z_0-9]+)`\) ?(?<extra>[ A-Z]+)?/';
$constraint_count = preg_match_all($constraint_regex, $create->{'Create Table'}, $constraints);
for ($i = 0; $i < $constraint_count; $i++) {
$constraint_name = $constraints['name'][$i];
$output[$table]['Constraints'][$constraint_name] = [
'name' => $constraint_name,
'foreign_key' => $constraints['foreign_key'][$i],
'table' => $constraints['table'][$i],
'key' => $constraints['key'][$i],
'extra' => $constraints['extra'][$i],
];
}
}
}
return $output;
}
/**
* Get an array of the schema files.
* schema_version => full_file_name