1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugins\CoreAdminHome\Commands;
use Piwik\Common;
use Piwik\DataAccess\ArchiveTableCreator;
use Piwik\Date;
use Piwik\Db;
use Piwik\Plugin\ConsoleCommand;
/**
* Administration command that optimizes archive tables (even if they use InnoDB).
*/
class OptimizeArchiveTables extends ConsoleCommand
{
public const ALL_TABLES_STRING = 'all';
public const CURRENT_MONTH_STRING = 'now';
protected function configure()
{
$this->setName('database:optimize-archive-tables');
$this->setDescription("Runs an OPTIMIZE TABLE query on the specified archive tables.");
$this->addRequiredArgument(
"dates",
"The months of the archive tables to optimize. Use '" . self::ALL_TABLES_STRING . "' for all dates or '" .
self::CURRENT_MONTH_STRING . "' to optimize the current month only.",
null,
true
);
$this->addNoValueOption('dry-run', null, 'For testing purposes.');
$this->setHelp("This command can be used to ease or automate maintenance. Instead of manually running "
. "OPTIMIZE TABLE queries, the command can be used.\n\nYou should run the command if you find your "
. "archive tables grow and do not shrink after purging. Optimizing them will reclaim some space.");
}
protected function doExecute(): int
{
$input = $this->getInput();
$dryRun = $input->getOption('dry-run');
$tableMonths = $this->getTableMonthsToOptimize();
foreach ($tableMonths as $month) {
$this->optimizeTable($dryRun, 'archive_numeric_' . $month);
$this->optimizeTable($dryRun, 'archive_blob_' . $month);
}
return self::SUCCESS;
}
private function optimizeTable($dryRun, $table)
{
$output = $this->getOutput();
$output->write("Optimizing table '$table'...");
if ($dryRun) {
$output->write("[dry-run, not optimising table]");
} else {
Db\Schema::getInstance()->optimizeTables([Common::prefixTable($table)], $force = true);
}
$output->writeln("Done.");
}
private function getTableMonthsToOptimize()
{
$dateSpecifiers = $this->getInput()->getArgument('dates');
if (count($dateSpecifiers) === 1) {
$dateSpecifier = reset($dateSpecifiers);
if ($dateSpecifier == self::ALL_TABLES_STRING) {
return $this->getAllArchiveTableMonths();
} elseif ($dateSpecifier == self::CURRENT_MONTH_STRING) {
$now = Date::factory('now');
return array(ArchiveTableCreator::getTableMonthFromDate($now));
} elseif (strpos($dateSpecifier, 'last') === 0) {
$lastN = substr($dateSpecifier, 4);
if (!ctype_digit($lastN)) {
throw new \Exception("Invalid lastN specifier '$lastN'. The end must be an integer, eg, last1 or last2.");
}
if ($lastN <= 0) {
throw new \Exception("Invalid lastN value '$lastN'.");
}
return $this->getLastNTableMonths((int)$lastN);
}
}
$tableMonths = array();
foreach ($dateSpecifiers as $date) {
$date = Date::factory($date);
$tableMonths[] = ArchiveTableCreator::getTableMonthFromDate($date);
}
return $tableMonths;
}
private function getAllArchiveTableMonths()
{
$tableMonths = array();
foreach (ArchiveTableCreator::getTablesArchivesInstalled() as $table) {
$tableMonths[] = ArchiveTableCreator::getDateFromTableName($table);
}
return $tableMonths;
}
/**
* @param int $lastN
* @return string[]
*/
private function getLastNTableMonths($lastN)
{
$now = Date::factory('now');
$result = array();
for ($i = 0; $i < $lastN; ++$i) {
$date = $now->subMonth($i + 1);
$result[] = ArchiveTableCreator::getTableMonthFromDate($date);
}
return $result;
}
}
|