mirror of
https://github.com/syncthing/syncthing.git
synced 2025-12-23 22:18:14 -05:00
feat: add syncthing debug database-statistics command (#10117)
This adds a command that shows database statistics. Currently it requires a fork of the sqlite package to add the dbstats virtual table; the modernc variant already has it. This also provides the canonical mapping between folder ID and database file, for tinkerers... ``` % ./bin/syncthing debug database-statistics DATABASE FOLDER ID TABLE SIZE FILL ======== ====== == ===== ==== ==== main.db - folders 4 KiB 8.4 % main.db - folders_database_name 4 KiB 6.0 % main.db - kv 4 KiB 41.1 % main.db - schemamigrations 4 KiB 3.9 % main.db - sqlite_autoindex_folders_1 4 KiB 3.7 % ... folder.0007-txpxsvyd.db w3ejt-fn4dm indexids 4 KiB 1.5 % folder.0007-txpxsvyd.db w3ejt-fn4dm kv 4 KiB 0.8 % folder.0007-txpxsvyd.db w3ejt-fn4dm mtimes 608 KiB 81.5 % folder.0007-txpxsvyd.db w3ejt-fn4dm schemamigrations 4 KiB 3.9 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_autoindex_blocklists_1 4108 KiB 89.5 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_autoindex_blocks_1 700020 KiB 88.1 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_autoindex_devices_1 4 KiB 3.6 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_autoindex_kv_1 4 KiB 0.6 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_schema 12 KiB 45.9 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_sequence 4 KiB 1.0 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_stat1 4 KiB 12.2 % folder.0007-txpxsvyd.db w3ejt-fn4dm sqlite_stat4 4 KiB 0.2 % folder.0007-txpxsvyd.db w3ejt-fn4dm (total) 1906020 KiB 92.8 % main.db + children - (total) 2205888 KiB 92.0 % ```
This commit is contained in:
69
internal/db/sqlite/db_stats.go
Normal file
69
internal/db/sqlite/db_stats.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (C) 2025 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package sqlite
|
||||
|
||||
type DatabaseStatistics struct {
|
||||
Name string `json:"name"`
|
||||
FolderID string `json:"folderID,omitempty"`
|
||||
Tables []TableStatistics `json:"tables"`
|
||||
Total TableStatistics `json:"total"`
|
||||
Children []DatabaseStatistics `json:"children,omitempty"`
|
||||
}
|
||||
|
||||
type TableStatistics struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Size int64 `json:"size"`
|
||||
Unused int64 `json:"unused"`
|
||||
}
|
||||
|
||||
func (s *DB) Statistics() (*DatabaseStatistics, error) {
|
||||
ts, total, err := s.tableStats()
|
||||
if err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
ds := DatabaseStatistics{
|
||||
Name: s.baseName,
|
||||
Tables: ts,
|
||||
Total: total,
|
||||
}
|
||||
|
||||
err = s.forEachFolder(func(fdb *folderDB) error {
|
||||
tables, total, err := fdb.tableStats()
|
||||
if err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
ds.Children = append(ds.Children, DatabaseStatistics{
|
||||
Name: fdb.baseName,
|
||||
FolderID: fdb.folderID,
|
||||
Tables: tables,
|
||||
Total: total,
|
||||
})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
|
||||
return &ds, nil
|
||||
}
|
||||
|
||||
func (s *baseDB) tableStats() ([]TableStatistics, TableStatistics, error) {
|
||||
var stats []TableStatistics
|
||||
if err := s.stmt(`
|
||||
SELECT name, pgsize AS size, unused FROM dbstat
|
||||
WHERE aggregate=true
|
||||
ORDER BY name
|
||||
`).Select(&stats); err != nil {
|
||||
return nil, TableStatistics{}, wrap(err)
|
||||
}
|
||||
var total TableStatistics
|
||||
for _, s := range stats {
|
||||
total.Size += s.Size
|
||||
total.Unused += s.Unused
|
||||
}
|
||||
return stats, total, nil
|
||||
}
|
||||
Reference in New Issue
Block a user