Skip to content

Commit f581f37

Browse files
authored
Optimize creation of expression and partial indices (#7559)
* Refactor index condition/expression evaluation into classes. Speed up (appr. 10x) creation and validation time for conditional indices. * Simplified NULL handling when index keys are composed * Refactor index key creation (from record). Optimize evaluation of index expressions. * Adjustments after Vlad's review * Remove redundant variables
1 parent bc7b17c commit f581f37

File tree

9 files changed

+562
-512
lines changed

9 files changed

+562
-512
lines changed

src/jrd/btr.cpp

Lines changed: 350 additions & 366 deletions
Large diffs are not rendered by default.

src/jrd/btr.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,108 @@ class IndexErrorContext
327327
bool isLocationDefined;
328328
};
329329

330+
// Helper classes to allow efficient evaluation of index conditions/expressions
331+
332+
class IndexCondition
333+
{
334+
public:
335+
IndexCondition(thread_db* tdbb, index_desc* idx);
336+
~IndexCondition();
337+
338+
bool evaluate(Record* record) const;
339+
340+
private:
341+
thread_db* const m_tdbb;
342+
BoolExprNode* m_condition = nullptr;
343+
Request* m_request = nullptr;
344+
};
345+
346+
class IndexExpression
347+
{
348+
public:
349+
IndexExpression(thread_db* tdbb, index_desc* idx);
350+
~IndexExpression();
351+
352+
dsc* evaluate(Record* record) const;
353+
354+
private:
355+
thread_db* const m_tdbb;
356+
ValueExprNode* m_expression = nullptr;
357+
Request* m_request = nullptr;
358+
};
359+
360+
// Index key wrapper
361+
362+
class IndexKey
363+
{
364+
public:
365+
IndexKey(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
366+
: m_tdbb(tdbb), m_relation(relation), m_index(idx),
367+
m_keyType((idx->idx_flags & idx_unique) ? INTL_KEY_UNIQUE : INTL_KEY_SORT),
368+
m_segments(idx->idx_count), m_expression(tdbb, idx)
369+
{}
370+
371+
IndexKey(thread_db* tdbb, jrd_rel* relation, index_desc* idx,
372+
USHORT keyType, USHORT segments)
373+
: m_tdbb(tdbb), m_relation(relation), m_index(idx),
374+
m_keyType(keyType), m_segments(segments), m_expression(tdbb, idx)
375+
{
376+
fb_assert(m_segments && m_segments <= idx->idx_count);
377+
}
378+
379+
idx_e compose(Record* record);
380+
381+
operator temporary_key*()
382+
{
383+
return &m_key;
384+
}
385+
386+
temporary_key* operator->()
387+
{
388+
return &m_key;
389+
}
390+
391+
bool operator==(const IndexKey& other) const
392+
{
393+
if (m_key.key_length != other.m_key.key_length)
394+
return false;
395+
396+
return !memcmp(m_key.key_data, other.m_key.key_data, m_key.key_length);
397+
}
398+
399+
bool operator!=(const IndexKey& other) const
400+
{
401+
if (m_key.key_length != other.m_key.key_length)
402+
return true;
403+
404+
return memcmp(m_key.key_data, other.m_key.key_data, m_key.key_length);
405+
}
406+
407+
// Return ordinal number of the first NULL segment
408+
USHORT getNullSegment() const
409+
{
410+
USHORT nulls = m_key.key_nulls;
411+
412+
for (USHORT i = 0; nulls; i++)
413+
{
414+
if (nulls & 1)
415+
return i;
416+
417+
nulls >>= 1;
418+
}
419+
420+
return MAX_USHORT;
421+
}
422+
423+
private:
424+
thread_db* const m_tdbb;
425+
jrd_rel* const m_relation;
426+
index_desc* const m_index;
427+
const USHORT m_keyType;
428+
const USHORT m_segments;
429+
temporary_key m_key;
430+
IndexExpression m_expression;
431+
};
330432

331433
} //namespace Jrd
332434

src/jrd/btr_proto.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,12 @@ void BTR_create(Jrd::thread_db*, Jrd::IndexCreation&, Jrd::SelectivityList&);
3535
bool BTR_delete_index(Jrd::thread_db*, Jrd::win*, USHORT);
3636
bool BTR_description(Jrd::thread_db*, Jrd::jrd_rel*, Ods::index_root_page*, Jrd::index_desc*, USHORT);
3737
bool BTR_check_condition(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*);
38-
DSC* BTR_eval_expression(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*, bool&);
38+
dsc* BTR_eval_expression(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*);
3939
void BTR_evaluate(Jrd::thread_db*, const Jrd::IndexRetrieval*, Jrd::RecordBitmap**, Jrd::RecordBitmap*);
4040
UCHAR* BTR_find_leaf(Ods::btree_page*, Jrd::temporary_key*, UCHAR*, USHORT*, bool, int);
4141
Ods::btree_page* BTR_find_page(Jrd::thread_db*, const Jrd::IndexRetrieval*, Jrd::win*, Jrd::index_desc*,
4242
Jrd::temporary_key*, Jrd::temporary_key*, bool = true);
4343
void BTR_insert(Jrd::thread_db*, Jrd::win*, Jrd::index_insertion*);
44-
Jrd::idx_e BTR_key(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::Record*, Jrd::index_desc*, Jrd::temporary_key*,
45-
const USHORT, USHORT = 0);
4644
USHORT BTR_key_length(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*);
4745
Ods::btree_page* BTR_left_handoff(Jrd::thread_db*, Jrd::win*, Ods::btree_page*, SSHORT);
4846
bool BTR_lookup(Jrd::thread_db*, Jrd::jrd_rel*, USHORT, Jrd::index_desc*, Jrd::RelationPages*);

0 commit comments

Comments
 (0)