diff --git a/Moosh/Command/Moodle39/Report/DbStats.php b/Moosh/Command/Moodle39/Report/DbStats.php index fb689504..ecaa2fbd 100755 --- a/Moosh/Command/Moodle39/Report/DbStats.php +++ b/Moosh/Command/Moodle39/Report/DbStats.php @@ -1,55 +1,151 @@ "mdl_log", + "grades" => "mdl_grade_grades", + "grades_history" => "mdl_grade_grades_history", +]; + + + +/** + * Command returns moodle database stats. For format check Moosh web docs. + */ class DbStats extends MooshCommand { public function __construct() { parent::__construct('stats', 'db'); $this->addOption('j|json', 'generate output using json format'); + $this->addOption('e|extended', 'generate extended stats for every table, always in json'); $this->addOption('H|no-human-readable', 'Do not display sizes in human-readble strings'); } public function execute() { + $options = $this->expandedOptions; + + if(isset($options['extended'])) { + $results = $this->fetchStats(); + + // returns full json stats + $results->tables = array_values($results->tables); + + echo json_encode($results); + } else { + // returns minimal stats + $results = $this->fetchStats(3, array_values(TABLE_NAMES)); + + // non-breaking space prevents from formatting as size + foreach($results->tables as $key => $table) { + $results->tables[$key]->rowCount = $table->rowCount . "\u{00A0}"; + } + + $stats = $this->mapStatsToSimpleFormat($results); + + $this->display($stats, $options['json'], !$options['no-human-readable']); + } + } + + /** + * Fetches database stats and returns plain results. Returns object containing size (int) + * and tables (array). Additionally, method may include tables provided in $additionalTableStats argument. + * @param non-negative-int|null $limit results limit + * @param string[] $additionalTableStats array of table names + * @return object + */ + public function fetchStats($limit = null, $additionalTableStats = []) { global $DB, $CFG; - $options = $this->expandedOptions; + if($limit < 0 || !($limit === null || is_int($limit))) { + throw new \InvalidArgumentException("limit must be a positive integer or null."); + } + + if(!is_array($additionalTableStats)) { + throw new \InvalidArgumentException("additionalTableStats must be an array."); + } + + // fetching general info + $informationSchemaSql = " + SELECT table_name AS 'name', + ROUND(data_length + index_length) AS 'size' + FROM information_schema.TABLES + WHERE table_schema = '$CFG->dbname' + ORDER BY (data_length + index_length) DESC + "; + + $results = $DB->get_records_sql($informationSchemaSql); + + // formatting query result, adding row count and calculating size + $values = array_values($results); + $resultsLength = count($values); + if(is_null($limit) || $limit > $resultsLength) { + $limit = $resultsLength; + } + + $databaseSize = 0; + $tableData = []; + foreach($values as $index => $result) { + $databaseSize += $result->size; - $sql = "SELECT table_name AS 'table', - ROUND(((data_length + index_length))) AS 'size' - FROM information_schema.TABLES - WHERE table_schema = '" . $CFG->dbname . "' - ORDER BY (data_length + index_length) DESC"; - $results = $DB->get_records_sql($sql); - - $databasesize = 0; - $topsizes = []; - $topnames = []; - foreach ($results as $result) { - if (!isset($topsizes[0])) { - $topsizes[0] = $result->size; - $topnames[0] = $result->table; - } else if (!isset($topsizes[1])) { - $topsizes[1] = $result->size; - $topnames[1] = $result->table; - } else if (!isset($topsizes[2])) { - $topsizes[2] = $result->size; - $topnames[2] = $result->table; + // we only calculate size and skips other actions when limit is reached + // we include tables from additionalTableStats + if($index >= $limit && !in_array($result->name, $additionalTableStats)) { + continue; } - $databasesize += $result->size; + + // querying row count + $tableName = $result->name; + + $countResult = $DB->get_records_sql("SELECT COUNT(*) AS 'count' from $tableName"); + + $firstRow = array_values($countResult)[0]; + + $result->rowCount = strval($firstRow->count); + + $tableData[$result->name] = $result; } - $data = ['Database size' => $databasesize, - 'Biggest table name' => $topnames[0], - 'Biggest table size' => $topsizes[0], - '2nd biggest table name' => $topnames[1], - '2nd biggest table size' => $topsizes[1], - '3rd biggest table name' => $topnames[2], - '3rd biggest table size' => $topsizes[2], + return (object) [ + 'size' => $databaseSize, + 'tables' => $tableData ]; + } - $this->display($data, $options['json'], !$options['no-human-readable']); + /** + * Maps results to array with simple keys and values. + * @param \stdClass $results full stats data + * @return array stat names with values + */ + public function mapStatsToSimpleFormat($results) { + $tables = $results->tables; + $tablesIndexed = array_values($tables); + + return ['Database size' => $results->size, + 'Biggest table name' => $tablesIndexed[0]->name, + 'Biggest table size' => $tablesIndexed[0]->size, + 'Biggest table number of records' => $tablesIndexed[0]->rowCount, + '2nd biggest table name' => $tablesIndexed[1]->name, + '2nd biggest table size' => $tablesIndexed[1]->size, + '2nd biggest table number of records' => $tablesIndexed[1]->rowCount, + '3rd biggest table name' => $tablesIndexed[2]->name, + '3rd biggest table size' => $tablesIndexed[2]->size, + '3rd biggest table number of records' => $tablesIndexed[2]->rowCount, + 'Log table size' => $tables[TABLE_NAMES['log']]->size, + 'Log table number of records' => $tables[TABLE_NAMES['log']]->rowCount, + 'Grades table size' => $tables[TABLE_NAMES['grades']]->size, + 'Grades table number of records' => $tables[TABLE_NAMES['grades']]->rowCount, + 'Grades history table size' => $tables[TABLE_NAMES['grades_history']]->size, + 'Grades history table number of records' => $tables[TABLE_NAMES['grades_history']]->rowCount, + ]; } } diff --git a/www/commands/index.md b/www/commands/index.md index 5a5520b5..154e36f4 100755 --- a/www/commands/index.md +++ b/www/commands/index.md @@ -1084,8 +1084,10 @@ Outputs data in json format when run using --json option. db-stats -------- -Shows the total size of the Moodle database and the biggest tables. -With -H or -j options the sizes will be shown in bytes (ie "286720" instead of "280KB"). +Shows the total size of the Moodle database, the top 3 biggest tables and tables: log, grades, grades history. +With -H, -j or -e options the sizes will be shown in bytes (ie "286720" instead of "280KB"). + +Using extended option (-e) it shows all tables. Example 1: Show me basic database statistics, formatted for human consumption. @@ -1094,6 +1096,10 @@ Example 1: Show me basic database statistics, formatted for human consumption. Example 2: Database statistics in JSON format. moosh db-stats -j + +Example 3: Extended database statistics in json format. It provides statistics for each table + + moosh db-stats -e debug-off ---------