1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +01:00

Provide "bin/storage analyze" and make "bin/storage upgrade" run analysis automatically

Summary:
Ref T12819. Normallly "ANALYZE TABLE" is like sprinkling magic pixie dust on the database and hoping it will make "good vibes" that cause it to go faster, but in at least some concrete cases with the ngrams tables there really was a key cardinality issue which ANALYZE TABLE corrected, fixing bogus query plans.

Add `bin/storage analyze` to analyze all tables, and make `bin/storage upgrade` run it after adjustment if `--no-adjust` is not specified, and make `bin/storage adjust` run it always.

This runs in a couple seconds and should never hurt anything, so it should be fine to sprinkle lots of pixie dust into the `bin/storage` workflow.

Test Plan: Ran `bin/storage analyze`. Ran `bin/storage upgrade`, saw analyze run. Totally felt great vibes and really aligned chakras on the database.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12819

Differential Revision: https://secure.phabricator.com/D18573
This commit is contained in:
epriestley 2017-09-07 13:37:41 -07:00
parent f1193afa94
commit 8e9f049626
3 changed files with 79 additions and 0 deletions

View file

@ -4088,6 +4088,7 @@ phutil_register_library_map(array(
'PhabricatorStorageFixtureScopeGuard' => 'infrastructure/testing/fixture/PhabricatorStorageFixtureScopeGuard.php', 'PhabricatorStorageFixtureScopeGuard' => 'infrastructure/testing/fixture/PhabricatorStorageFixtureScopeGuard.php',
'PhabricatorStorageManagementAPI' => 'infrastructure/storage/management/PhabricatorStorageManagementAPI.php', 'PhabricatorStorageManagementAPI' => 'infrastructure/storage/management/PhabricatorStorageManagementAPI.php',
'PhabricatorStorageManagementAdjustWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php', 'PhabricatorStorageManagementAdjustWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php',
'PhabricatorStorageManagementAnalyzeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementAnalyzeWorkflow.php',
'PhabricatorStorageManagementDatabasesWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php', 'PhabricatorStorageManagementDatabasesWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php',
'PhabricatorStorageManagementDestroyWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php', 'PhabricatorStorageManagementDestroyWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php',
'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php', 'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php',
@ -9679,6 +9680,7 @@ phutil_register_library_map(array(
'PhabricatorStorageFixtureScopeGuard' => 'Phobject', 'PhabricatorStorageFixtureScopeGuard' => 'Phobject',
'PhabricatorStorageManagementAPI' => 'Phobject', 'PhabricatorStorageManagementAPI' => 'Phobject',
'PhabricatorStorageManagementAdjustWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementAdjustWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementAnalyzeWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementDatabasesWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDatabasesWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementDestroyWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDestroyWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow',

View file

@ -0,0 +1,19 @@
<?php
final class PhabricatorStorageManagementAnalyzeWorkflow
extends PhabricatorStorageManagementWorkflow {
protected function didConstruct() {
$this
->setName('analyze')
->setExamples('**analyze**')
->setSynopsis(
pht('Run "ANALYZE TABLE" on tables to improve performance.'));
}
public function didExecute(PhutilArgumentParser $args) {
$this->analyzeTables();
return 0;
}
}

View file

@ -137,6 +137,15 @@ abstract class PhabricatorStorageManagementWorkflow
try { try {
$err = $this->doAdjustSchemata($api, $unsafe); $err = $this->doAdjustSchemata($api, $unsafe);
// Analyze tables if we're not doing a dry run and adjustments are either
// all clear or have minor errors like surplus tables.
if (!$this->dryRun) {
$should_analyze = (($err == 0) || ($err == 2));
if ($should_analyze) {
$this->analyzeTables();
}
}
} catch (Exception $ex) { } catch (Exception $ex) {
$lock->unlock(); $lock->unlock();
throw $ex; throw $ex;
@ -1163,4 +1172,53 @@ abstract class PhabricatorStorageManagementWorkflow
->lock(); ->lock();
} }
final protected function analyzeTables() {
// Analyzing tables can sometimes have a significant effect on query
// performance, particularly for the fulltext ngrams tables. See T12819
// for some specific examples.
$api = $this->getSingleAPI();
$conn = $api->getConn(null);
$patches = $this->getPatches();
$databases = $api->getDatabaseList($patches, true);
$this->logInfo(
pht('ANALYZE'),
pht('Analyzing tables...'));
$targets = array();
foreach ($databases as $database) {
queryfx($conn, 'USE %C', $database);
$tables = queryfx_all($conn, 'SHOW TABLE STATUS');
foreach ($tables as $table) {
$table_name = $table['Name'];
$targets[] = array(
'database' => $database,
'table' => $table_name,
);
}
}
$bar = id(new PhutilConsoleProgressBar())
->setTotal(count($targets));
foreach ($targets as $target) {
queryfx(
$conn,
'ANALYZE TABLE %T.%T',
$target['database'],
$target['table']);
$bar->update(1);
}
$bar->done();
$this->logOkay(
pht('ANALYZED'),
pht(
'Analyzed %d table(s).',
count($targets)));
}
} }