8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 17:23:03 +01:00

gstat: Print detailed blob statistics and table size (#8394)

* Print detailed blob statistics and table size

The new blob statistics looks as follow:

```
...
Empty pages: 0, full pages: 0
Blobs: 9, total length: 1451015, blob pages: 182
    Level 0: 3, total length: 15, blob pages: 0
    Level 1: 6, total length: 1451000, blob pages: 182
Table size: 1515520 bytes
Fill distribution:
...
```

* Add new message instead of modifying existing one

---------

Co-authored-by: Artyom Abakumov <artyom.abakumov@red-soft.ru>
This commit is contained in:
Artyom Abakumov 2025-01-20 11:38:56 +03:00 committed by GitHub
parent b1c4ea9026
commit b09e0aa54b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 27 deletions

View File

@ -60,3 +60,5 @@ FB_IMPL_MSG_NO_SYMBOL(GSTAT, 59, "Gstat execution time @1")
FB_IMPL_MSG_NO_SYMBOL(GSTAT, 60, "Gstat completion time @1") FB_IMPL_MSG_NO_SYMBOL(GSTAT, 60, "Gstat completion time @1")
FB_IMPL_MSG_NO_SYMBOL(GSTAT, 61, " Expected page inventory page @1") FB_IMPL_MSG_NO_SYMBOL(GSTAT, 61, " Expected page inventory page @1")
FB_IMPL_MSG_NO_SYMBOL(GSTAT, 62, "Generator pages: total @1, encrypted @2, non-crypted @3") FB_IMPL_MSG_NO_SYMBOL(GSTAT, 62, "Generator pages: total @1, encrypted @2, non-crypted @3")
FB_IMPL_MSG_NO_SYMBOL(GSTAT, 63, " Table size: @1 bytes")
FB_IMPL_MSG_NO_SYMBOL(GSTAT, 64, " Level @1: @2, total length: @3, blob pages: @4")

View File

@ -123,6 +123,22 @@ struct dba_fmt
bool fmt_used; bool fmt_used;
}; };
inline constexpr ULONG MAX_BLOB_LEVELS = 3;
struct dba_blob_statistics
{
FB_UINT64 blob_count = 0;
FB_UINT64 blob_space = 0;
FB_UINT64 blob_pages = 0;
dba_blob_statistics& operator+=(const dba_blob_statistics& rhs)
{
blob_count += rhs.blob_count;
blob_space += rhs.blob_space;
blob_pages += rhs.blob_pages;
return *this;
}
};
struct dba_rel struct dba_rel
{ {
dba_rel* rel_next; dba_rel* rel_next;
@ -147,10 +163,7 @@ struct dba_rel
FB_UINT64 rel_fragments; FB_UINT64 rel_fragments;
FB_UINT64 rel_fragment_space; FB_UINT64 rel_fragment_space;
FB_UINT64 rel_max_fragments; FB_UINT64 rel_max_fragments;
FB_UINT64 rel_blobs_level_0; dba_blob_statistics rel_blob_statistics[MAX_BLOB_LEVELS];
FB_UINT64 rel_blobs_level_1;
FB_UINT64 rel_blobs_level_2;
FB_UINT64 rel_blob_space;
ULONG rel_fill_distribution[BUCKETS]; ULONG rel_fill_distribution[BUCKETS];
FB_UINT64 rel_format_space; FB_UINT64 rel_format_space;
FB_UINT64 rel_total_space; FB_UINT64 rel_total_space;
@ -1024,16 +1037,46 @@ int gstat(Firebird::UtilSvc* uSvc)
// msg 47: " Big record pages: @1 // msg 47: " Big record pages: @1
} }
if (relation->rel_blobs_level_0 || relation->rel_blobs_level_1 || relation->rel_blobs_level_2) // Blobs are analyzing only when the record option is set
if (sw_record)
{ {
dba_print(false, 48, SafeArg() << (relation->rel_blobs_level_0 + relation->rel_blobs_level_1 + dba_blob_statistics blobsTotal;
relation->rel_blobs_level_2) << relation->rel_blob_space << for (ULONG i = 0; i < MAX_BLOB_LEVELS; ++i)
relation->rel_blob_pages); {
blobsTotal += relation->rel_blob_statistics[i];
}
if (blobsTotal.blob_count)
{
dba_print(false, 48, SafeArg()
<< blobsTotal.blob_count
<< blobsTotal.blob_space
<< blobsTotal.blob_pages);
// msg 48: " Blobs: @1, total length: @2, blob pages: @3 // msg 48: " Blobs: @1, total length: @2, blob pages: @3
dba_print(false, 49, SafeArg() << relation->rel_blobs_level_0 << relation->rel_blobs_level_1 << for (ULONG i = 0; i < MAX_BLOB_LEVELS; ++i)
relation->rel_blobs_level_2); {
// msg 49: " Level 0: @1, Level 1: @2, Level 2: @3 const dba_blob_statistics& blob_level = relation->rel_blob_statistics[i];
if (blob_level.blob_count > 0)
{
dba_print(false, 49, SafeArg()
<< i
<< blob_level.blob_count
<< blob_level.blob_space
<< blob_level.blob_pages);
// msg 64: " Level @1: @2, total length: @3, blob pages: @4
}
}
}
const FB_SIZE_T tableSize = tddba->page_size * (
relation->rel_pointer_pages +
relation->rel_data_pages +
blobsTotal.blob_pages);
dba_print(false, 63, SafeArg() << tableSize); // msg 63: "Table size: @1 bytes
} }
dba_print(false, 13); // msg 13: " Fill distribution:" dba_print(false, 13); // msg 13: " Fill distribution:"
@ -1401,32 +1444,31 @@ static bool analyze_data_page( dba_rel* relation, const data_page* page, bool sw
static void analyze_blob(dba_rel* relation, const blh* blob, int length) static void analyze_blob(dba_rel* relation, const blh* blob, int length)
{ {
relation->rel_blob_space += blob->blh_length; fb_assert(blob->blh_level < MAX_BLOB_LEVELS);
if (!blob->blh_level) dba_blob_statistics& blob_level = relation->rel_blob_statistics[blob->blh_level];
{
relation->rel_blobs_level_0++; ++blob_level.blob_count;
} blob_level.blob_space += blob->blh_length;
else
if (blob->blh_level != 0)
{ {
const int slots = (length - BLH_SIZE) / static_cast<int>(sizeof(SLONG)); const int slots = (length - BLH_SIZE) / static_cast<int>(sizeof(SLONG));
relation->rel_blob_pages += slots; ULONG blobPages = slots;
if (blob->blh_level == 1)
{
relation->rel_blobs_level_1++;
}
else
{
relation->rel_blobs_level_2++;
if (blob->blh_level == 2)
{
SLONG pages[MAX_PAGE_SIZE / sizeof(SLONG)]; SLONG pages[MAX_PAGE_SIZE / sizeof(SLONG)];
memcpy(pages, blob->blh_page, slots * sizeof(SLONG)); memcpy(pages, blob->blh_page, slots * sizeof(SLONG));
for (int i = 0; i < slots; i++) for (int i = 0; i < slots; i++)
{ {
const blob_page* bpage = (const blob_page*) db_read(pages[i]); const blob_page* bpage = (const blob_page*) db_read(pages[i]);
relation->rel_blob_pages += bpage->blp_length / sizeof(SLONG); blobPages += bpage->blp_length / sizeof(SLONG);
} }
} }
relation->rel_blob_pages += blobPages;
blob_level.blob_pages += blobPages;
} }
} }