Skip to content

Commit

Permalink
Merge pull request #7521 from FirebirdSQL/work/gh-7494
Browse files Browse the repository at this point in the history
Impovement #7494 : Firebird performance issue - non necessary index r…
  • Loading branch information
hvlad authored Apr 7, 2023
2 parents e3da2da + 50c7ee3 commit 495070c
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 64 deletions.
145 changes: 82 additions & 63 deletions src/jrd/btr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,13 @@ static ULONG fast_load(thread_db*, IndexCreation&, SelectivityList&);

static index_root_page* fetch_root(thread_db*, WIN*, const jrd_rel*, const RelationPages*);
static UCHAR* find_node_start_point(btree_page*, temporary_key*, UCHAR*, USHORT*,
bool, bool, bool = false, RecordNumber = NO_VALUE);
bool, int, bool = false, RecordNumber = NO_VALUE);

static UCHAR* find_area_start_point(btree_page*, const temporary_key*, UCHAR*,
USHORT*, bool, bool, RecordNumber = NO_VALUE);
USHORT*, bool, int, RecordNumber = NO_VALUE);

static ULONG find_page(btree_page*, const temporary_key*, const index_desc*, RecordNumber = NO_VALUE,
bool = false);
int = 0);

static contents garbage_collect(thread_db*, WIN*, ULONG);
static void generate_jump_nodes(thread_db*, btree_page*, jumpNodeList*, USHORT,
Expand Down Expand Up @@ -631,30 +631,37 @@ static void checkForLowerKeySkip(bool& skipLowerKey,
}
else
{
// Check if we have a duplicate node (for the same page)
if (node.prefix < lower.key_length)
if ((lower.key_length == node.prefix + node.length) ||
(lower.key_length <= node.prefix + node.length) && partLower)
{
if (node.prefix + node.length == lower.key_length)
skipLowerKey = (memcmp(node.data, lower.key_data + node.prefix, node.length) == 0);
else
skipLowerKey = false;
}
else if ((node.prefix == lower.key_length) && node.length)
{
// In case of multi-segment check segment-number else
// it's a different key
if (partLower)
const UCHAR* p = node.data, *q = lower.key_data + node.prefix;
const UCHAR* const end = lower.key_data + lower.key_length;
while (q < end)
{
const USHORT segnum = idx.idx_count - (UCHAR)((idx.idx_flags & idx_descending) ?
(*node.data) ^ -1 : *node.data);
if (*p++ != *q++)
{
skipLowerKey = false;
break;
}
}

if ((q >= end) && (p < node.data + node.length) && skipLowerKey && partLower)
{
const bool descending = idx.idx_flags & idx_descending;

// since key length always is multiplier of (STUFF_COUNT + 1) (for partial
// compound keys) and we passed lower key completely then p pointed
// us to the next segment number and we can use this fact to calculate
// how many segments is equal to lower key
const USHORT segnum = idx.idx_count - (UCHAR)(descending ? ((*p) ^ -1) : *p);

if (segnum < retrieval->irb_lower_count) {
skipLowerKey = false;
}
}
else {
skipLowerKey = false;
}
}
else {
skipLowerKey = false;
}
}
}
Expand Down Expand Up @@ -725,37 +732,7 @@ void BTR_evaluate(thread_db* tdbb, const IndexRetrieval* retrieval, RecordBitmap
{
IndexNode node;
node.readNode(pointer, true);

if ((lower->key_length == node.prefix + node.length) ||
(lower->key_length <= node.prefix + node.length) && partLower)
{
const UCHAR* p = node.data, *q = lower->key_data + node.prefix;
const UCHAR* const end = lower->key_data + lower->key_length;
while (q < end)
{
if (*p++ != *q++)
{
skipLowerKey = false;
break;
}
}

if ((q >= end) && (p < node.data + node.length) && skipLowerKey && partLower)
{
// since key length always is multiplier of (STUFF_COUNT + 1) (for partial
// compound keys) and we passed lower key completely then p pointed
// us to the next segment number and we can use this fact to calculate
// how many segments is equal to lower key
const USHORT segnum = idx.idx_count - (UCHAR) (descending ? ((*p) ^ -1) : *p);

if (segnum < retrieval->irb_lower_count) {
skipLowerKey = false;
}
}
}
else {
skipLowerKey = false;
}
checkForLowerKeySkip(skipLowerKey, partLower, node, *lower, idx, retrieval);
}
}
else
Expand Down Expand Up @@ -841,7 +818,7 @@ void BTR_evaluate(thread_db* tdbb, const IndexRetrieval* retrieval, RecordBitmap


UCHAR* BTR_find_leaf(btree_page* bucket, temporary_key* key, UCHAR* value,
USHORT* return_value, bool descending, bool retrieval)
USHORT* return_value, bool descending, int retrieval)
{
/**************************************
*
Expand Down Expand Up @@ -4182,7 +4159,7 @@ static index_root_page* fetch_root(thread_db* tdbb, WIN* window, const jrd_rel*
static UCHAR* find_node_start_point(btree_page* bucket, temporary_key* key,
UCHAR* value,
USHORT* return_value, bool descending,
bool retrieval, bool pointer_by_marker,
int retrieval, bool pointer_by_marker,
RecordNumber find_record_number)
{
/**************************************
Expand Down Expand Up @@ -4260,9 +4237,21 @@ static UCHAR* find_node_start_point(btree_page* bucket, temporary_key* key,
{
while (true)
{
if (q == nodeEnd || (retrieval && p == key_end))
if (q == nodeEnd)
goto done;

if (retrieval && p == key_end)
{
if ((retrieval & irb_partial) && !(retrieval & irb_starting))
{
// check segment
const bool sameSegment = ((p - STUFF_COUNT > key->key_data) && p[-(STUFF_COUNT + 1)] == *q);
if (sameSegment)
break;
}
goto done;
}

if (p == key_end || *p > *q)
break;

Expand Down Expand Up @@ -4323,7 +4312,7 @@ static UCHAR* find_node_start_point(btree_page* bucket, temporary_key* key,
static UCHAR* find_area_start_point(btree_page* bucket, const temporary_key* key,
UCHAR* value,
USHORT* return_prefix, bool descending,
bool retrieval, RecordNumber find_record_number)
int retrieval, RecordNumber find_record_number)
{
/**************************************
*
Expand Down Expand Up @@ -4426,7 +4415,17 @@ static UCHAR* find_area_start_point(btree_page* bucket, const temporary_key* key

if (retrieval && keyPointer == keyEnd)
{
done = true;
if ((retrieval & irb_partial) && !(retrieval & irb_starting))
{
// check segment
const bool sameSegment = ((keyPointer - STUFF_COUNT > key->key_data) && keyPointer[-(STUFF_COUNT + 1)] == *q);
if (!sameSegment)
done = true;
}
else
{
done = true;
}
break;
}

Expand Down Expand Up @@ -4529,7 +4528,7 @@ static UCHAR* find_area_start_point(btree_page* bucket, const temporary_key* key

static ULONG find_page(btree_page* bucket, const temporary_key* key,
const index_desc* idx, RecordNumber find_record_number,
bool retrieval)
int retrieval)
{
/**************************************
*
Expand Down Expand Up @@ -6414,7 +6413,6 @@ static bool scan(thread_db* tdbb, UCHAR* pointer, RecordBitmap** bitmap, RecordB
const bool skipUpperKey = (flag & irb_exclude_upper);
const bool partLower = (retrieval->irb_lower_count < idx->idx_count);
const bool partUpper = (retrieval->irb_upper_count < idx->idx_count);
USHORT upperPrefix = prefix;

// reset irb_equality flag passed for optimization
flag &= ~(irb_equality | irb_ignore_null_value_key);
Expand Down Expand Up @@ -6456,31 +6454,52 @@ static bool scan(thread_db* tdbb, UCHAR* pointer, RecordBitmap** bitmap, RecordB
else if (node.prefix <= prefix)
{
prefix = node.prefix;
upperPrefix = prefix;
USHORT byteInSegment = prefix % (STUFF_COUNT + 1);
p = key->key_data + prefix;
const UCHAR* q = node.data;
USHORT l = node.length;
for (; l; --l, prefix++)
{
if (skipUpperKey && partUpper)
{
if (upperPrefix >= key->key_length)
if (p >= end_key && byteInSegment == 0)
{
const USHORT segnum =
idx->idx_count - (UCHAR)(descending ? ((*q) ^ -1) : *q) + 1;

if (segnum >= retrieval->irb_upper_count)
if (segnum > retrieval->irb_upper_count)
return false;

if (segnum == retrieval->irb_upper_count && !descending)
return false;
}

if (*p == *q)
upperPrefix++;
if (++byteInSegment > STUFF_COUNT)
byteInSegment = 0;
}

if (p >= end_key)
{
if (flag)
{
// Check if current node bytes is from the same segment as
// last byte of the key. If not, we have equality at that
// segment. Else, for ascending index, node is greater than
// the key and scan should be stopped.
// For descending index, the node is less than the key and
// scan shoud be continued.

if ((flag & irb_partial) && !(flag & irb_starting) &&
(p - STUFF_COUNT > key->key_data) && (p[-(STUFF_COUNT + 1)] == *q))
{
if (descending)
break;

return false;
}

break;
}

return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/jrd/btr_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ bool BTR_delete_index(Jrd::thread_db*, Jrd::win*, USHORT);
bool BTR_description(Jrd::thread_db*, Jrd::jrd_rel*, Ods::index_root_page*, Jrd::index_desc*, USHORT);
DSC* BTR_eval_expression(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*, bool&);
void BTR_evaluate(Jrd::thread_db*, const Jrd::IndexRetrieval*, Jrd::RecordBitmap**, Jrd::RecordBitmap*);
UCHAR* BTR_find_leaf(Ods::btree_page*, Jrd::temporary_key*, UCHAR*, USHORT*, bool, bool);
UCHAR* BTR_find_leaf(Ods::btree_page*, Jrd::temporary_key*, UCHAR*, USHORT*, bool, int);
Ods::btree_page* BTR_find_page(Jrd::thread_db*, const Jrd::IndexRetrieval*, Jrd::win*, Jrd::index_desc*,
Jrd::temporary_key*, Jrd::temporary_key*, bool = true);
void BTR_insert(Jrd::thread_db*, Jrd::win*, Jrd::index_insertion*);
Expand Down

0 comments on commit 495070c

Please sign in to comment.