diff --git a/internal/backends/collection_test.go b/internal/backends/collection_test.go index ce984a466277..206fd27fbfbc 100644 --- a/internal/backends/collection_test.go +++ b/internal/backends/collection_test.go @@ -189,19 +189,20 @@ func TestCollectionStats(t *testing.T) { db, err := b.Database(dbName) require.NoError(t, err) + var c backends.Collection cNames := []string{"collectionOne", "collectionTwo"} for _, cName := range cNames { err = db.CreateCollection(ctx, &backends.CreateCollectionParams{Name: cName}) require.NoError(t, err) - } - c, err := db.Collection(cNames[0]) - require.NoError(t, err) + c, err = db.Collection(cName) + require.NoError(t, err) - _, err = c.InsertAll(ctx, &backends.InsertAllParams{ - Docs: []*types.Document{must.NotFail(types.NewDocument("_id", types.NewObjectID()))}, - }) - require.NoError(t, err) + _, err = c.InsertAll(ctx, &backends.InsertAllParams{ + Docs: []*types.Document{must.NotFail(types.NewDocument("_id", types.NewObjectID()))}, + }) + require.NoError(t, err) + } dbStatsRes, err := db.Stats(ctx, new(backends.DatabaseStatsParams)) require.NoError(t, err) diff --git a/internal/backends/postgresql/database_test.go b/internal/backends/postgresql/database_test.go index 3ca5a4c3fe07..5b3d8f9c173f 100644 --- a/internal/backends/postgresql/database_test.go +++ b/internal/backends/postgresql/database_test.go @@ -69,7 +69,7 @@ func TestDatabaseStats(t *testing.T) { require.NoError(t, err) require.NotZero(t, res.SizeTotal) require.Equal(t, res.CountCollections, int64(len(cNames))) - require.NotZero(t, res.SizeCollections) + require.Zero(t, res.SizeCollections) require.Zero(t, res.CountObjects) require.NotZero(t, res.CountIndexes) require.NotZero(t, res.SizeIndexes) // includes metadata table's indexes diff --git a/internal/backends/postgresql/postgresql.go b/internal/backends/postgresql/postgresql.go index 4a7d54b37e01..af4c465f04e2 100644 --- a/internal/backends/postgresql/postgresql.go +++ b/internal/backends/postgresql/postgresql.go @@ -67,10 +67,23 @@ func collectionsStats(ctx context.Context, p *pgxpool.Pool, dbName string, list args = append(args, c.TableName) } + // The table size is the size used by collection objects. It excludes visibility map, + // initialization fork, free space map and TOAST. The `main` `pg_relation_size` is + // used, however it is not updated immediately after operation such as DELETE + // unless VACUUM is called, ANALYZE does not update pg_relation_size in this case. + // + // The smallest difference in size that `pg_relation_size` reports appears to be 8KB. + // Because of that inserting or deleting a single small object may not change the size. + // + // See also https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE, + // visibility map https://www.postgresql.org/docs/current/storage-vm.html, + // initialization fork https://www.postgresql.org/docs/current/storage-init.html, + // free space map https://www.postgresql.org/docs/current/storage-fsm.html and + // TOAST https://www.postgresql.org/docs/current/storage-toast.html. q = fmt.Sprintf(` SELECT COALESCE(SUM(c.reltuples), 0), - COALESCE(SUM(pg_table_size(c.oid)), 0), + COALESCE(SUM(pg_relation_size(c.oid,'main')), 0), COALESCE(SUM(pg_indexes_size(c.oid)), 0) FROM pg_tables AS t LEFT JOIN pg_class AS c ON c.relname = t.tablename AND c.relnamespace = quote_ident(t.schemaname)::regnamespace diff --git a/internal/backends/sqlite/sqlite.go b/internal/backends/sqlite/sqlite.go index 45e7e4d32da0..473f19a19440 100644 --- a/internal/backends/sqlite/sqlite.go +++ b/internal/backends/sqlite/sqlite.go @@ -70,6 +70,16 @@ func collectionsStats(ctx context.Context, db *fsql.DB, list []*metadata.Collect indexes += int64(len(c.Settings.Indexes)) } + // The table size is the size used by collection objects. The `pgsize` of `dbstat` + // table does not include freelist pages, pointer-map pages, and the lock page. + // + // If rows are deleted from a page but there are other rows on that same page, + // the page won't be moved to freelist pages. + // + // The smallest difference in size that `pgsize` reports appears to be 4KB. + // Because of that inserting or deleting a single small object may not change the size. + // + // See https://www.sqlite.org/dbstat.html and https://www.sqlite.org/fileformat.html. q = fmt.Sprintf(` SELECT SUM(pgsize) FROM dbstat