File: OptimizeArchiveTables.php

package info (click to toggle)
matomo 5.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 95,068 kB
  • sloc: php: 289,425; xml: 127,249; javascript: 112,130; python: 202; sh: 178; makefile: 20; sql: 10
file content (130 lines) | stat: -rw-r--r-- 4,303 bytes parent folder | download | duplicates (2)
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;
    }
}