diff --git a/src/include/gen/ids.h b/src/include/gen/ids.h index 9c02f6add4..1506626649 100644 --- a/src/include/gen/ids.h +++ b/src/include/gen/ids.h @@ -154,6 +154,7 @@ #define f_seg_name 0 #define f_seg_field 1 #define f_seg_position 2 +#define f_seg_statistics 3 #define f_idx_name 0 #define f_idx_relation 1 #define f_idx_id 2 diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index 30de1fac7d..125c7e0a95 100644 --- a/src/jrd/btr.cpp +++ b/src/jrd/btr.cpp @@ -160,7 +160,7 @@ static void copy_key(KEY *, KEY *); static CONTENTS delete_node(TDBB, WIN *, BTN); static void delete_tree(TDBB, USHORT, USHORT, SLONG, SLONG); static DSC *eval(TDBB, JRD_NOD, DSC *, bool *); -static SLONG fast_load(TDBB, JRD_REL, IDX *, USHORT, SCB, float *); +static SLONG fast_load(TDBB, JRD_REL, IDX *, USHORT, SCB, SelectivityList&); static IRT fetch_root(TDBB, WIN *, JRD_REL); static SLONG find_node(BTR, KEY *, bool); static CONTENTS garbage_collect(TDBB, WIN *, SLONG); @@ -241,7 +241,9 @@ USHORT BTR_all(TDBB tdbb, void BTR_create(TDBB tdbb, JRD_REL relation, IDX * idx, - USHORT key_length, SCB sort_handle, float *selectivity) + USHORT key_length, + SCB sort_handle, + SelectivityList& selectivity) { /************************************** * @@ -270,7 +272,7 @@ void BTR_create(TDBB tdbb, IRT root = (IRT) CCH_FETCH(tdbb, &window, LCK_write, pag_root); CCH_MARK(tdbb, &window); root->irt_rpt[idx->idx_id].irt_root = idx->idx_root; - root->irt_rpt[idx->idx_id].irt_stuff.irt_selectivity = *selectivity; + root->irt_rpt[idx->idx_id].irt_stuff.irt_selectivity = selectivity.back(); root->irt_rpt[idx->idx_id].irt_flags &= ~irt_in_progress; if (dbb->dbb_wal) { @@ -1573,7 +1575,7 @@ retry: } -float BTR_selectivity(TDBB tdbb, JRD_REL relation, USHORT id) +void BTR_selectivity(TDBB tdbb, JRD_REL relation, USHORT id, SelectivityList& selectivity) { /************************************** * @@ -1596,13 +1598,13 @@ float BTR_selectivity(TDBB tdbb, JRD_REL relation, USHORT id) IRT root = fetch_root(tdbb, &window, relation); if (!root) { - return 0.0; + return; } SLONG page = root->irt_rpt[id].irt_root; if (root->irt_count <= id || !page) { CCH_RELEASE(tdbb, &window); - return 0.0; + return; } window.win_flags = WIN_large_scan; window.win_scans = 1; @@ -1667,15 +1669,16 @@ float BTR_selectivity(TDBB tdbb, JRD_REL relation, USHORT id) CCH_RELEASE_TAIL(tdbb, &window); // calculate the selectivity and store it on the root page - float selectivity = (float) ((nodes) ? 1.0 / (float) (nodes - duplicates) : 0.0); + const USHORT count = root->irt_rpt[id].irt_keys; + selectivity.grow(count); + selectivity.back() = + (float) ((nodes) ? 1.0 / (float) (nodes - duplicates) : 0.0); window.win_page = relation->rel_index_root; window.win_flags = 0; root = (IRT) CCH_FETCH(tdbb, &window, LCK_write, pag_root); CCH_MARK(tdbb, &window); - root->irt_rpt[id].irt_stuff.irt_selectivity = selectivity; + root->irt_rpt[id].irt_stuff.irt_selectivity = selectivity.back(); CCH_RELEASE(tdbb, &window); - - return selectivity; } @@ -2449,7 +2452,9 @@ static DSC *eval(TDBB tdbb, JRD_NOD node, DSC * temp, bool *missing) static SLONG fast_load(TDBB tdbb, JRD_REL relation, IDX * idx, - USHORT key_length, SCB sort_handle, float *selectivity) + USHORT key_length, + SCB sort_handle, + SelectivityList& selectivity) { /************************************** * @@ -2794,7 +2799,9 @@ static SLONG fast_load(TDBB tdbb, } CCH_flush(tdbb, (USHORT) FLUSH_ALL, 0); - *selectivity = (float) ((count) ? (1. / (double) (count - duplicates)) : 0); + selectivity.grow(idx->idx_count); + selectivity.back() = + (float) ((count) ? (1. / (double) (count - duplicates)) : 0); return window->win_page; diff --git a/src/jrd/btr.h b/src/jrd/btr.h index 575fbdb82e..7cd8ebccfe 100644 --- a/src/jrd/btr.h +++ b/src/jrd/btr.h @@ -27,12 +27,11 @@ #ifndef JRD_BTR_H #define JRD_BTR_H +#include "../common/classes/array.h" #include "../jrd/jrd_blks.h" #include "../jrd/constants.h" #include "../include/fb_blk.h" -#include - #include "../jrd/err_proto.h" /* Index error types */ /* 64 turns out not to be enough indexes */ @@ -209,5 +208,7 @@ typedef struct jrd_exp { #define NEXT_EXPANDED(xxx,yyy) (BTX) ((UCHAR*) xxx->btx_data + (yyy)->btn_prefix + (yyy)->btn_length) +typedef Firebird::HalfStaticArray SelectivityList; + #endif /* JRD_BTR_H */ diff --git a/src/jrd/btr_proto.h b/src/jrd/btr_proto.h index 4b850b54ab..5307b7f163 100644 --- a/src/jrd/btr_proto.h +++ b/src/jrd/btr_proto.h @@ -29,7 +29,7 @@ #include "../jrd/req.h" USHORT BTR_all(TDBB, jrd_rel*, idx**, idx**, str**, SLONG*); -void BTR_create(TDBB, jrd_rel*, idx*, USHORT, scb*, float*); +void BTR_create(TDBB, jrd_rel*, idx*, USHORT, scb*, SelectivityList&); void BTR_delete_index(TDBB, win*, USHORT); bool BTR_description(JRD_REL, irt*, idx*, SSHORT); void BTR_evaluate(tdbb*, irb*, sbm**); @@ -47,7 +47,7 @@ btn* BTR_next_node(btn*, btx**); btn* BTR_previous_node(btn*, btx**); void BTR_remove(tdbb*, win*, iib*); void BTR_reserve_slot(TDBB, jrd_rel*, jrd_tra*, idx*); -float BTR_selectivity(TDBB, jrd_rel*, USHORT); +void BTR_selectivity(TDBB, jrd_rel*, USHORT, SelectivityList&); #endif // JRD_BTR_PROTO_H diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index 3c209c6aab..210600ab5e 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -682,7 +682,7 @@ void DFW_post_work_arg( JRD_TRA transaction, DFW work, DSC * desc, USHORT id) } -void DFW_update_index( DFW work, USHORT id, float selectivity) +void DFW_update_index(const TEXT* name, USHORT id, const SelectivityList& selectivity) { /************************************** * @@ -702,15 +702,35 @@ void DFW_update_index( DFW work, USHORT id, float selectivity) tdbb = GET_THREAD_DATA; dbb = tdbb->tdbb_database; + if (dbb->dbb_ods_version >= ODS_VERSION11) { + + request = (BLK) CMP_find_request(tdbb, irq_m_index_seg, IRQ_REQUESTS); + + FOR(REQUEST_HANDLE request) + SEG IN RDB$INDEX_SEGMENTS WITH SEG.RDB$INDEX_NAME EQ name + SORTED BY SEG.RDB$FIELD_POSITION + if (!REQUEST(irq_m_index_seg)) + REQUEST(irq_m_index_seg) = (BLK)request; + MODIFY SEG USING + SEG.RDB$STATISTICS = + selectivity.getCount() ? selectivity[SEG.RDB$FIELD_POSITION] : 0.0; + END_MODIFY; + END_FOR; + + if (!REQUEST(irq_m_index_seg)) + REQUEST(irq_m_index_seg) = (BLK)request; + } + request = (BLK) CMP_find_request(tdbb, irq_m_index, IRQ_REQUESTS); FOR(REQUEST_HANDLE request) - IDX IN RDB$INDICES WITH IDX.RDB$INDEX_NAME EQ work->dfw_name + IDX IN RDB$INDICES WITH IDX.RDB$INDEX_NAME EQ name if (!REQUEST(irq_m_index)) REQUEST(irq_m_index) = (BLK)request; MODIFY IDX USING IDX.RDB$INDEX_ID = id + 1; - IDX.RDB$STATISTICS = selectivity; + IDX.RDB$STATISTICS = + selectivity.getCount() ? selectivity.back() : 0.0; END_MODIFY; END_FOR; @@ -1502,7 +1522,6 @@ static bool create_index( TDBB tdbb, JRD_REL relation, partner_relation; IDX idx; int key_count; - float selectivity; SSHORT text_type; SSHORT collate; BLK handle; @@ -1597,12 +1616,11 @@ static bool create_index( TDBB tdbb, } if (IDX.RDB$INDEX_ID && IDX.RDB$STATISTICS < 0.0) { - MODIFY IDX - IDX.RDB$STATISTICS = - IDX_statistics( tdbb, - relation, - (USHORT)(IDX.RDB$INDEX_ID - 1)); - END_MODIFY; + SelectivityList selectivity(tdbb->tdbb_default); + const USHORT id = IDX.RDB$INDEX_ID - 1; + IDX_statistics(tdbb, relation, id, selectivity); + DFW_update_index(work->dfw_name, id, selectivity); + EXE_unwind(tdbb, (JRD_REQ)request); return false; } @@ -1782,15 +1800,11 @@ static bool create_index( TDBB tdbb, } fb_assert(work->dfw_id == dbb->dbb_max_idx); - IDX_create_index( tdbb, - relation, - &idx, - (UCHAR*) work->dfw_name, - &work->dfw_id, - transaction, - &selectivity); + SelectivityList selectivity(tdbb->tdbb_default); + IDX_create_index(tdbb, relation, &idx, (UCHAR*) work->dfw_name, + &work->dfw_id, transaction, selectivity); fb_assert(work->dfw_id == idx.idx_id); - DFW_update_index(work, idx.idx_id, selectivity); + DFW_update_index(work->dfw_name, idx.idx_id, selectivity); if (partner_relation) { diff --git a/src/jrd/dfw_proto.h b/src/jrd/dfw_proto.h index 974e9e813d..51e7dbc7e9 100644 --- a/src/jrd/dfw_proto.h +++ b/src/jrd/dfw_proto.h @@ -32,6 +32,6 @@ void DFW_perform_work(jrd_tra*); void DFW_perform_post_commit_work(jrd_tra*); dfw* DFW_post_work(jrd_tra*, enum dfw_t, dsc*, USHORT); void DFW_post_work_arg(jrd_tra*, dfw*, dsc*, USHORT); -void DFW_update_index(dfw*, USHORT, float); +void DFW_update_index(const TEXT*, USHORT, const SelectivityList&); #endif // JRD_DFW_PROTO_H diff --git a/src/jrd/idx.cpp b/src/jrd/idx.cpp index 195c4e7161..5916186902 100644 --- a/src/jrd/idx.cpp +++ b/src/jrd/idx.cpp @@ -169,7 +169,9 @@ void IDX_create_index( JRD_REL relation, IDX * idx, UCHAR * index_name, - USHORT * index_id, JRD_TRA transaction, float *selectivity) + USHORT * index_id, + JRD_TRA transaction, + SelectivityList& selectivity) { /************************************** * @@ -791,7 +793,7 @@ IDX_E IDX_modify_check_constraints(TDBB tdbb, } -float IDX_statistics(TDBB tdbb, JRD_REL relation, USHORT id) +void IDX_statistics(TDBB tdbb, JRD_REL relation, USHORT id, SelectivityList& selectivity) { /************************************** * @@ -807,7 +809,7 @@ float IDX_statistics(TDBB tdbb, JRD_REL relation, USHORT id) SET_TDBB(tdbb); - return BTR_selectivity(tdbb, relation, id); + BTR_selectivity(tdbb, relation, id, selectivity); } diff --git a/src/jrd/idx_proto.h b/src/jrd/idx_proto.h index 12063a5417..ae98aa968f 100644 --- a/src/jrd/idx_proto.h +++ b/src/jrd/idx_proto.h @@ -32,7 +32,7 @@ void IDX_check_access(TDBB, class Csb *, struct jrd_rel *, struct jrd_rel *, struct jrd_fld *); void IDX_create_index(TDBB, struct jrd_rel *, struct idx *, UCHAR *, - USHORT *, class jrd_tra *, float *); + USHORT *, class jrd_tra *, SelectivityList&); struct idb *IDX_create_index_block(TDBB, struct jrd_rel *, USHORT); void IDX_delete_index(TDBB, struct jrd_rel *, USHORT); void IDX_delete_indices(TDBB, struct jrd_rel *); @@ -45,7 +45,7 @@ enum idx_e IDX_modify(struct tdbb *, struct rpb *, struct rpb *, enum idx_e IDX_modify_check_constraints(TDBB, struct rpb *, struct rpb *, class jrd_tra *, struct jrd_rel **, USHORT *); -float IDX_statistics(TDBB, struct jrd_rel *, USHORT); +void IDX_statistics(TDBB, struct jrd_rel *, USHORT, SelectivityList&); enum idx_e IDX_store(struct tdbb *, struct rpb *, class jrd_tra *, struct jrd_rel **, USHORT *); diff --git a/src/jrd/irq.h b/src/jrd/irq.h index ee21aed30c..dd5d210f46 100644 --- a/src/jrd/irq.h +++ b/src/jrd/irq.h @@ -108,7 +108,8 @@ #define irq_r_gen_id_num 72 /* lookup generator by ID. */ #define irq_verify_role_name 73 /* ensure role exists in roles & user_privileges. */ #define irq_l_relation_defsec 74 /* check the default sec class name against rel. */ +#define irq_m_index_seg 75 /* modify per-segment index selectivity */ -#define irq_MAX 75 +#define irq_MAX 76 #endif /* JRD_IRQ_H */ diff --git a/src/jrd/pcmet.epp b/src/jrd/pcmet.epp index 68c7b68c85..a29b0ba892 100644 --- a/src/jrd/pcmet.epp +++ b/src/jrd/pcmet.epp @@ -70,7 +70,6 @@ int PCMET_expression_index( DBB dbb; JRD_REL relation; IDX idx; - float selectivity; PLB default_pool, new_pool = NULL; CSB csb; JRD_REQ current_request; @@ -101,12 +100,13 @@ int PCMET_expression_index( relation->rel_name = MET_save_name(tdbb, REL.RDB$RELATION_NAME); relation->rel_length = strlen(relation->rel_name); - } if (IDX.RDB$INDEX_ID && IDX.RDB$STATISTICS < 0.0) { - MODIFY IDX - IDX.RDB$STATISTICS = - IDX_statistics(tdbb, relation, - IDX.RDB$INDEX_ID - 1); - END_MODIFY; + } + if (IDX.RDB$INDEX_ID && IDX.RDB$STATISTICS < 0.0) { + SelectivityList selectivity(tdbb->tdbb_default); + const USHORT id = IDX.RDB$INDEX_ID - 1; + IDX_statistics(tdbb, relation, id, selectivity); + DFW_update_index(work->dfw_name, id, selectivity); + EXE_unwind(tdbb, REQUEST(irq_c_exp_index)); return FALSE; } @@ -174,6 +174,8 @@ int PCMET_expression_index( /* Actually create the index */ + SelectivityList selectivity(tdbb->tdbb_default); + current_request = tdbb->tdbb_request; tdbb->tdbb_request = idx.idx_expression_request; IDX_create_index(tdbb, relation, &idx, work->dfw_name, NULL,