Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move methods related to optimizing database tables to schema classes #22355

Merged
merged 2 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ The Product Changelog at **[matomo.org/changelog](https://matomo.org/changelog)*

* The dependency `jQuery.dotdotdot` has been removed. Please use pure CSS instead or include the library in your plugin if needed.

## Deprecations

The methods `Db::isOptimizeInnoDBSupported` and `Db::optimizeTables` have been deprecated. Use `Db\Schema::getInstance()->isOptimizeInnoDBSupported` and `Db\Schema::getInstance()->optimizeTables` instead

## Matomo 5.1.0

### Breaking Changes
Expand Down
72 changes: 10 additions & 62 deletions core/Db.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Exception;
use Piwik\Db\Adapter;
use Piwik\Db\Schema;

/**
* Contains SQL related helper functions for Piwik's MySQL database.
Expand Down Expand Up @@ -466,63 +467,17 @@ public static function deleteAllRows($table, $where, $orderBy, $maxRowsPerQuery
* Table names must be prefixed (see {@link Piwik\Common::prefixTable()}).
* @param bool $force If true, the `OPTIMIZE TABLE` query will be run even if InnoDB tables are being used.
* @return bool
* @deprecated will be removed in Matomo 6
* use Schema::getInstance()->optimizeTables() instead
*/
public static function optimizeTables($tables, $force = false)
{
$optimize = Config::getInstance()->General['enable_sql_optimize_queries'];

if (
empty($optimize)
&& !$force
) {
return false;
}

if (empty($tables)) {
return false;
}

if (!is_array($tables)) {
$tables = array($tables);
}

if (
!self::isOptimizeInnoDBSupported()
&& !$force
) {
// filter out all InnoDB tables
$myisamDbTables = array();
foreach (self::getTableStatus() as $row) {
if (
strtolower($row['Engine']) == 'myisam'
&& in_array($row['Name'], $tables)
) {
$myisamDbTables[] = $row['Name'];
}
}

$tables = $myisamDbTables;
}

if (empty($tables)) {
return false;
}

// optimize the tables
$success = true;
foreach ($tables as &$t) {
$ok = self::query('OPTIMIZE TABLE ' . $t);
if (!$ok) {
$success = false;
}
}

return $success;
}

private static function getTableStatus()
{
return Db::fetchAll("SHOW TABLE STATUS");
$tables = !is_array($tables) ? [$tables] : $tables;
mneudert marked this conversation as resolved.
Show resolved Hide resolved
return Schema::getInstance()->optimizeTables($tables, (bool) $force);
}

/**
Expand Down Expand Up @@ -912,19 +867,12 @@ public static function isQueryLogEnabled()
return self::$logQueries;
}

/**
* @deprecated will be removed with Matomo 6
* use Schema::getInstance()->isOptimizeInnoDBSupported() instead
*/
public static function isOptimizeInnoDBSupported($version = null)
{
if ($version === null) {
$version = Db::fetchOne("SELECT VERSION()");
}

$version = strtolower($version);

if (strpos($version, "mariadb") === false) {
return false;
}

$semanticVersion = strstr($version, '-', $beforeNeedle = true);
return version_compare($semanticVersion, '10.1.1', '>=');
return Db\Schema::getInstance()->isOptimizeInnoDBSupported();
}
}
26 changes: 26 additions & 0 deletions core/Db/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,30 @@ public function supportsComplexColumnUpdates(): bool
{
return $this->getSchema()->supportsComplexColumnUpdates();
}

/**
* Returns if the schema supports `OPTIMIZE TABLE` statements for innodb tables
*
* @return bool
*/
public function isOptimizeInnoDBSupported(): bool
{
return $this->getSchema()->isOptimizeInnoDBSupported();
}

/**
* Runs an `OPTIMIZE TABLE` query on the supplied table or tables.
*
* Tables will only be optimized if the `[General] enable_sql_optimize_queries` INI config option is
* set to **1**.
*
* @param string|array $tables The name of the table to optimize or an array of tables to optimize.
* Table names must be prefixed (see {@link Piwik\Common::prefixTable()}).
* @param bool $force If true, the `OPTIMIZE TABLE` query will be run even if InnoDB tables are being used.
* @return bool
*/
public function optimizeTables(array $tables, bool $force = false): bool
{
return $this->getSchema()->optimizeTables($tables, $force);
}
}
7 changes: 7 additions & 0 deletions core/Db/Schema/Mariadb.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,11 @@ public function addMaxExecutionTimeHintToQuery(string $sql, float $limit): strin

return $sql;
}

public function isOptimizeInnoDBSupported(): bool
{
$version = strtolower($this->getVersion());
$semanticVersion = strstr($version, '-', $beforeNeedle = true);
return version_compare($semanticVersion, '10.1.1', '>=');
}
}
74 changes: 74 additions & 0 deletions core/Db/Schema/Mysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Exception;
use Piwik\Common;
use Piwik\Concurrency\Lock;
use Piwik\Config;
use Piwik\Date;
use Piwik\Db\SchemaInterface;
use Piwik\Db;
Expand Down Expand Up @@ -688,6 +689,69 @@ public function getTableCreateOptions(): string
return $options;
}

public function optimizeTables(array $tables, bool $force = false): bool
{
$optimize = Config::getInstance()->General['enable_sql_optimize_queries'];

if (
empty($optimize)
&& !$force
) {
return false;
}

if (empty($tables)) {
return false;
}

if (
!$this->isOptimizeInnoDBSupported()
&& !$force
) {
// filter out all InnoDB tables
$myisamDbTables = array();
foreach ($this->getTableStatus() as $row) {
if (
strtolower($row['Engine']) == 'myisam'
&& in_array($row['Name'], $tables)
) {
$myisamDbTables[] = $row['Name'];
}
}

$tables = $myisamDbTables;
}

if (empty($tables)) {
return false;
}

// optimize the tables
$success = true;
foreach ($tables as &$t) {
$ok = Db::query('OPTIMIZE TABLE ' . $t);
if (!$ok) {
$success = false;
}
}

return $success;
}

public function isOptimizeInnoDBSupported(): bool
{
$version = strtolower($this->getVersion());

// Note: This check for MariaDb is here on purpose, so it's working correctly for people
// having MySQL still configured, when using MariaDb
if (strpos($version, "mariadb") === false) {
return false;
}

$semanticVersion = strstr($version, '-', $beforeNeedle = true);
return version_compare($semanticVersion, '10.1.1', '>=');
}

protected function getDatabaseCreateOptions(): string
{
$charset = DbHelper::getDefaultCharset();
Expand Down Expand Up @@ -715,6 +779,16 @@ private function getTablePrefix()
return $this->getDbSettings()->getTablePrefix();
}

protected function getVersion(): string
{
return Db::fetchOne("SELECT VERSION()");
}

protected function getTableStatus()
{
return Db::fetchAll("SHOW TABLE STATUS");
}

private function getDb()
{
return Db::get();
Expand Down
11 changes: 11 additions & 0 deletions core/Db/Schema/Tidb.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ public function getTableCreateOptions(): string
return $options;
}

public function isOptimizeInnoDBSupported(): bool
{
return false;
}

public function optimizeTables(array $tables, bool $force = false): bool
{
// OPTIMIZE TABLE not supported for TiDb
return false;
}

protected function getDatabaseCreateOptions(): string
{
$charset = DbHelper::getDefaultCharset();
Expand Down
20 changes: 20 additions & 0 deletions core/Db/SchemaInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,24 @@ public function getDefaultPort(): int;
* @return string
*/
public function getTableCreateOptions(): string;

/**
* Returns if performing on `OPTIMIZE TABLE` is supported for InnoDb tables
*
* @return bool
*/
public function isOptimizeInnoDBSupported(): bool;

/**
* Runs an `OPTIMIZE TABLE` query on the supplied table or tables.
*
* Tables will only be optimized if the `[General] enable_sql_optimize_queries` INI config option is
* set to **1**.
*
* @param array $tables The name of the table to optimize or an array of tables to optimize.
* Table names must be prefixed (see {@link Piwik\Common::prefixTable()}).
* @param bool $force If true, the `OPTIMIZE TABLE` query will be run even if InnoDB tables are being used.
* @return bool
*/
public function optimizeTables(array $tables, bool $force = false): bool;
}
2 changes: 1 addition & 1 deletion plugins/CoreAdminHome/Commands/DeleteLogsData.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ private function optimizeTables()

$prefixedTable = Common::prefixTable($table);

$done = Db::optimizeTables($prefixedTable);
$done = Db\Schema::getInstance()->optimizeTables([$prefixedTable]);

if ($done) {
$this->getOutput()->writeln("done. <comment>" . $timer . "</comment>");
Expand Down
2 changes: 1 addition & 1 deletion plugins/CoreAdminHome/Commands/OptimizeArchiveTables.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private function optimizeTable($dryRun, $table)
if ($dryRun) {
$output->write("[dry-run, not optimising table]");
} else {
Db::optimizeTables(Common::prefixTable($table), $force = true);
Db\Schema::getInstance()->optimizeTables([Common::prefixTable($table)], $force = true);
}

$output->writeln("Done.");
Expand Down
4 changes: 2 additions & 2 deletions plugins/CoreAdminHome/Commands/PurgeOldArchiveData.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ private function optimizeArchiveTables($dates)
foreach ($dates as $date) {
$numericTable = ArchiveTableCreator::getNumericTable($date);
$this->performTimedPurging("Optimizing table $numericTable...", function () use ($numericTable) {
Db::optimizeTables($numericTable, $force = true);
Db\Schema::getInstance()->optimizeTables([$numericTable], $force = true);
});

$blobTable = ArchiveTableCreator::getBlobTable($date);
$this->performTimedPurging("Optimizing table $blobTable...", function () use ($blobTable) {
Db::optimizeTables($blobTable, $force = true);
Db\Schema::getInstance()->optimizeTables([$blobTable], $force = true);
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/CoreAdminHome/Tasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ public function purgeInvalidatedArchives()
public function optimizeArchiveTable()
{
$archiveTables = ArchiveTableCreator::getTablesArchivesInstalled();
Db::optimizeTables($archiveTables);
Db\Schema::getInstance()->optimizeTables($archiveTables);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion plugins/PrivacyManager/LogDataPurger.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public function purgeData($deleteLogsOlderThan, $deleteUnusedLogActions)
Piwik::postEvent('PrivacyManager.deleteLogsOlderThan', array($dateUpperLimit, $deleteLogsOlderThan));

// optimize table overhead after deletion
Db::optimizeTables($logTables);
Db\Schema::getInstance()->optimizeTables($logTables);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions plugins/PrivacyManager/ReportsPurger.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public function purgeData($optimize = false)
}

if ($optimize) {
Db::optimizeTables($oldBlobTables);
Db\Schema::getInstance()->optimizeTables($oldBlobTables);
}
}

Expand Down Expand Up @@ -152,7 +152,7 @@ public function purgeData($optimize = false)
}

if ($optimize) {
Db::optimizeTables($oldNumericTables);
Db\Schema::getInstance()->optimizeTables($oldNumericTables);
}
}
}
Expand Down
Loading
Loading