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

CORE-3295: Estimate the actual record compression ratio in the optimizer.

This commit is contained in:
dimitr 2010-12-28 12:01:45 +00:00
parent 5b54095841
commit f19f33ad54

View File

@ -204,48 +204,74 @@ double DPM_cardinality(thread_db* tdbb, jrd_rel* relation, const Format* format)
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
// Estimated number of total records for this relation,
// we assume that the records are compressed to 50%
// Every record has also a header and a jump section (13 + 4)
USHORT minRecordSize = sizeof(Ods::data_page::dpg_repeat) + RHD_SIZE;
if (!(dbb->dbb_flags & DBB_no_reserve)) {
minRecordSize += RHDF_SIZE;
}
// Get the number of data-pages for this relation
SLONG dataPages = DPM_data_pages(tdbb, relation);
const SLONG dataPages = DPM_data_pages(tdbb, relation);
// AB: If we have only 1 data-page then the cardinality calculation
// is to worse to be usefull, therefore rely on the record count
// from the data-page.
// Calculate record count and total compressed record length
// on the first data page
if (dataPages == 1) {
RelationPages* relPages = relation->getPages(tdbb);
vcl* vector = relPages->rel_pages;
if (vector) {
WIN window(relPages->rel_pg_space_id, (*vector)[0]);
Ods::pointer_page* ppage =
(Ods::pointer_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_pointer);
USHORT recordCount = 0;
const SLONG* page = ppage->ppg_page;
if (*page) {
Ods::data_page* dpage =
(Ods::data_page*) CCH_HANDOFF(tdbb, &window, *page, LCK_read, pag_data);
recordCount = dpage->dpg_count;
}
CCH_RELEASE(tdbb, &window);
return (double) recordCount;
USHORT recordCount = 0, recordLength = 0;
RelationPages* relPages = relation->getPages(tdbb);
vcl* vector = relPages->rel_pages;
if (vector)
{
WIN window(relPages->rel_pg_space_id, (*vector)[0]);
Ods::pointer_page* ppage =
(Ods::pointer_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_pointer);
if (!ppage)
{
BUGCHECK(243);
// msg 243 missing pointer page in DPM_data_pages
}
const SLONG* page = ppage->ppg_page;
if (*page)
{
Ods::data_page* dpage =
(Ods::data_page*) CCH_HANDOFF(tdbb, &window, *page, LCK_read, pag_data);
const data_page::dpg_repeat* index = dpage->dpg_rpt;
const data_page::dpg_repeat* const end = index + dpage->dpg_count;
for (; index < end; index++)
{
if (index->dpg_offset)
{
recordCount++;
recordLength += index->dpg_length - RHD_SIZE;
}
}
}
CCH_RELEASE(tdbb, &window);
}
if (!format) {
// AB: If we have only 1 data-page then the cardinality calculation
// is to worse to be useful, therefore rely on the record count
// from the data-page.
if (dataPages == 1)
{
return (double) recordCount;
}
// Estimate total number of records for this relation
if (!format)
{
format = relation->rel_current_format;
}
return (double) dataPages * (dbb->dbb_page_size - DPG_SIZE) /
(minRecordSize + (format->fmt_length * 0.5));
static const double DEFAULT_COMPRESSION_RATIO = 0.5;
const USHORT compressedSize =
recordCount ? recordLength / recordCount :
format->fmt_length * DEFAULT_COMPRESSION_RATIO;
const USHORT recordSize = sizeof(Ods::data_page::dpg_repeat) +
ROUNDUP(compressedSize + RHD_SIZE, ODS_ALIGNMENT) +
(dbb->dbb_flags & DBB_no_reserve) ? 0 : SPACE_FUDGE;
return (double) dataPages * (dbb->dbb_page_size - DPG_SIZE) / recordSize;
}