mirror of https://gitee.com/bigwinds/arangodb
added selectivity estimates for some index types
This commit is contained in:
parent
436ac1adfc
commit
39603ebaf4
20
CHANGELOG
20
CHANGELOG
|
@ -1,6 +1,26 @@
|
|||
v2.5.0 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* added selectivity estimates for primary, edge, and hash indexes.
|
||||
|
||||
The selectivity estimates are returned by the `GET /_api/index` REST API method
|
||||
in a sub-attribute `selectivityEstimate` for each index that supports it. This
|
||||
attribute will be omitted for indexes that do not provide selectivity estimates.
|
||||
If provided, the selectivity estimate will be a numeric value between 0 and 1.
|
||||
|
||||
Selectivity estimates will also be reported in the result of `collection.getIndexes()`
|
||||
for all indexes that support this. If no selectivity estimate can be determined for
|
||||
an index, the attribute `selectivityEstimate` will be omitted here, too.
|
||||
|
||||
The web interface also shows selectivity estimates for each index that supports this.
|
||||
|
||||
Currently the following index types can provide selectivity estimates:
|
||||
- primary index
|
||||
- edge index
|
||||
- hash index (unique and non-unique)
|
||||
|
||||
No selectivity estimates will be provided when running in cluster mode.
|
||||
|
||||
* fixed issue #1226: arangod log issues
|
||||
|
||||
* added additional logger if arangod is started in foreground mode on a tty
|
||||
|
|
|
@ -4,7 +4,6 @@ require 'rspec'
|
|||
require 'arangodb.rb'
|
||||
|
||||
describe ArangoDB do
|
||||
api = "/_api/index"
|
||||
prefix = "api-index-hash"
|
||||
|
||||
################################################################################
|
||||
|
|
|
@ -457,6 +457,7 @@ SHELL_COMMON = \
|
|||
@top_srcdir@/js/common/tests/shell-cap-constraint-timecritical.js \
|
||||
@top_srcdir@/js/common/tests/shell-unique-constraint.js \
|
||||
@top_srcdir@/js/common/tests/shell-hash-index.js \
|
||||
@top_srcdir@/js/common/tests/shell-hash-index-noncluster.js \
|
||||
@top_srcdir@/js/common/tests/shell-fulltext.js \
|
||||
@top_srcdir@/js/common/tests/shell-graph.js
|
||||
|
||||
|
|
|
@ -115,25 +115,23 @@ namespace triagens {
|
|||
}
|
||||
|
||||
bool hasSelectivityEstimate () const {
|
||||
if (type == TRI_IDX_TYPE_PRIMARY_INDEX ||
|
||||
type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
return true;
|
||||
if (! hasInternals()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return getInternals()->_hasSelectivityEstimate;
|
||||
}
|
||||
|
||||
double selectivityEstimate () const {
|
||||
TRI_ASSERT_EXPENSIVE(hasSelectivityEstimate());
|
||||
TRI_index_t* internals = getInternals();
|
||||
|
||||
if (type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||
return 1.0;
|
||||
}
|
||||
if (type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
return TRI_SelectivityHashIndex(getInternals());
|
||||
}
|
||||
TRI_ASSERT(internals->_hasSelectivityEstimate);
|
||||
|
||||
TRI_ASSERT(false);
|
||||
return internals->selectivityEstimate(internals);
|
||||
}
|
||||
|
||||
inline bool hasInternals () const {
|
||||
return (internals != nullptr);
|
||||
}
|
||||
|
||||
TRI_index_t* getInternals () const {
|
||||
|
|
|
@ -761,7 +761,7 @@ double TRI_SelectivityHashArrayMulti (TRI_hash_array_multi_t* array) {
|
|||
size_t numTotal = array->_nrUsed + array->_nrOverflowUsed;
|
||||
|
||||
if (numTotal == 0) {
|
||||
return -1.0;
|
||||
return 1.0;
|
||||
}
|
||||
return static_cast<double>(array->_nrUsed) / static_cast<double>(numTotal);
|
||||
}
|
||||
|
|
|
@ -593,6 +593,20 @@ static int SizeHintHashIndex (TRI_index_t* idx,
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the hash index can provide a selectivity estimate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static double SelectivityEstimateHashIndex (TRI_index_t const* idx) {
|
||||
TRI_hash_index_t* hashIndex = (TRI_hash_index_t*) idx;
|
||||
|
||||
if (hashIndex->base._unique) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return TRI_SelectivityHashArrayMulti(&hashIndex->_hashArrayMulti);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -615,11 +629,13 @@ TRI_index_t* TRI_CreateHashIndex (TRI_document_collection_t* document,
|
|||
|
||||
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_HASH_INDEX, document, unique, false);
|
||||
|
||||
idx->memory = MemoryHashIndex;
|
||||
idx->json = JsonHashIndex;
|
||||
idx->insert = InsertHashIndex;
|
||||
idx->remove = RemoveHashIndex;
|
||||
idx->sizeHint = SizeHintHashIndex;
|
||||
idx->_hasSelectivityEstimate = true;
|
||||
idx->selectivityEstimate = SelectivityEstimateHashIndex;
|
||||
idx->memory = MemoryHashIndex;
|
||||
idx->json = JsonHashIndex;
|
||||
idx->insert = InsertHashIndex;
|
||||
idx->remove = RemoveHashIndex;
|
||||
idx->sizeHint = SizeHintHashIndex;
|
||||
|
||||
// ...........................................................................
|
||||
// Copy the contents of the path list vector into a new vector and store this
|
||||
|
|
|
@ -1299,7 +1299,7 @@ static void DropIndexCoordinator (const v8::FunctionCallbackInfo<v8::Value>& arg
|
|||
/// [
|
||||
/// { "id" : "example/0", "type" : "primary", "fields" : ["_id"] },
|
||||
/// { "id" : "example/991154", "unique" : false, "type" : "skiplist", "fields" : ["a", "b"] }
|
||||
/// ]
|
||||
/// ]
|
||||
///
|
||||
/// arango> db.example.dropIndex(i[0])
|
||||
/// false
|
||||
|
@ -1308,7 +1308,9 @@ static void DropIndexCoordinator (const v8::FunctionCallbackInfo<v8::Value>& arg
|
|||
/// true
|
||||
///
|
||||
/// arango> i = db.example.getIndexes();
|
||||
/// [{ "id" : "example/0", "type" : "primary", "fields" : ["_id"] }]
|
||||
/// [
|
||||
/// { "id" : "example/0", "type" : "primary", "fields" : ["_id"] }
|
||||
/// ]
|
||||
/// ```
|
||||
///
|
||||
/// @endDocuBlock
|
||||
|
@ -1422,7 +1424,7 @@ static void GetIndexesCoordinator (const v8::FunctionCallbackInfo<v8::Value>& ar
|
|||
/// @startDocuBlock collectionGetIndexes
|
||||
/// `getIndexes()`
|
||||
///
|
||||
/// Returns a list of all indexes defined for the collection.
|
||||
/// Returns an array of all indexes defined for the collection.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
|
|
|
@ -90,13 +90,15 @@ void TRI_InitIndex (TRI_index_t* idx,
|
|||
idx->_collection = document;
|
||||
idx->_unique = unique;
|
||||
idx->_sparse = sparse;
|
||||
idx->_hasSelectivityEstimate = false;
|
||||
|
||||
// init common functions
|
||||
idx->memory = nullptr;
|
||||
idx->removeIndex = nullptr;
|
||||
idx->cleanup = nullptr;
|
||||
idx->sizeHint = nullptr;
|
||||
idx->postInsert = nullptr;
|
||||
idx->selectivityEstimate = nullptr;
|
||||
idx->memory = nullptr;
|
||||
idx->removeIndex = nullptr;
|
||||
idx->cleanup = nullptr;
|
||||
idx->sizeHint = nullptr;
|
||||
idx->postInsert = nullptr;
|
||||
|
||||
LOG_TRACE("initialising index of type %s", TRI_TypeNameIndex(idx->_type));
|
||||
}
|
||||
|
@ -433,6 +435,9 @@ TRI_json_t* TRI_JsonIndex (TRI_memory_zone_t* zone,
|
|||
TRI_Insert3ObjectJson(zone, json, "id", TRI_CreateStringCopyJson(zone, number, strlen(number)));
|
||||
TRI_Insert3ObjectJson(zone, json, "type", TRI_CreateStringCopyJson(zone, TRI_TypeNameIndex(idx->_type), strlen(TRI_TypeNameIndex(idx->_type))));
|
||||
TRI_Insert3ObjectJson(zone, json, "unique", TRI_CreateBooleanJson(zone, idx->_unique));
|
||||
if (idx->_hasSelectivityEstimate) {
|
||||
TRI_Insert3ObjectJson(zone, json, "selectivityEstimate", TRI_CreateNumberJson(zone, idx->selectivityEstimate(idx)));
|
||||
}
|
||||
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, number);
|
||||
}
|
||||
|
@ -525,6 +530,14 @@ static size_t MemoryPrimary (TRI_index_t const* idx) {
|
|||
return idx->_collection->_primaryIndex._nrAlloc * sizeof(void*);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the selectivity estimate for the index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static double SelectivityEstimatePrimary (TRI_index_t const* idx) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief JSON description of a primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -565,10 +578,12 @@ TRI_index_t* TRI_CreatePrimaryIndex (TRI_document_collection_t* document) {
|
|||
|
||||
TRI_InitIndex(idx, 0, TRI_IDX_TYPE_PRIMARY_INDEX, document, true, false);
|
||||
|
||||
idx->memory = MemoryPrimary;
|
||||
idx->json = JsonPrimary;
|
||||
idx->insert = InsertPrimary;
|
||||
idx->remove = RemovePrimary;
|
||||
idx->_hasSelectivityEstimate = true;
|
||||
idx->selectivityEstimate = &SelectivityEstimatePrimary;
|
||||
idx->memory = MemoryPrimary;
|
||||
idx->json = JsonPrimary;
|
||||
idx->insert = InsertPrimary;
|
||||
idx->remove = RemovePrimary;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
@ -920,6 +935,16 @@ static size_t MemoryEdge (TRI_index_t const* idx) {
|
|||
TRI_MemoryUsageMultiPointer(&(((TRI_edge_index_t*) idx)->_edges_to));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a selectivity esimtate for the index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static double SelectivityEstimateEdge (TRI_index_t const* idx) {
|
||||
// return average selectivity of the two index parts
|
||||
return (TRI_SelectivityEstimateMultiPointer(&(((TRI_edge_index_t*) idx)->_edges_from)) +
|
||||
TRI_SelectivityEstimateMultiPointer(&(((TRI_edge_index_t*) idx)->_edges_to))) * 0.5;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief JSON description of edge index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1028,10 +1053,12 @@ TRI_index_t* TRI_CreateEdgeIndex (TRI_document_collection_t* document,
|
|||
|
||||
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_EDGE_INDEX, document, false, false);
|
||||
|
||||
idx->memory = MemoryEdge;
|
||||
idx->json = JsonEdge;
|
||||
idx->insert = InsertEdge;
|
||||
idx->remove = RemoveEdge;
|
||||
idx->_hasSelectivityEstimate = true;
|
||||
idx->selectivityEstimate = SelectivityEstimateEdge;
|
||||
idx->memory = MemoryEdge;
|
||||
idx->json = JsonEdge;
|
||||
idx->insert = InsertEdge;
|
||||
idx->remove = RemoveEdge;
|
||||
|
||||
idx->sizeHint = SizeHintEdge;
|
||||
|
||||
|
|
|
@ -101,7 +101,9 @@ typedef struct TRI_index_s {
|
|||
bool _unique;
|
||||
bool _ignoreNull;
|
||||
bool _sparse;
|
||||
bool _hasSelectivityEstimate;
|
||||
|
||||
double (*selectivityEstimate) (struct TRI_index_s const*);
|
||||
size_t (*memory) (struct TRI_index_s const*);
|
||||
TRI_json_t* (*json) (struct TRI_index_s const*);
|
||||
void (*removeIndex) (struct TRI_index_s*, struct TRI_document_collection_t*);
|
||||
|
|
|
@ -230,12 +230,13 @@
|
|||
<th class="collectionInfoTh">ID</th>
|
||||
<th class="collectionInfoTh">Type</th>
|
||||
<th class="collectionInfoTh">Unique</th>
|
||||
<th class="collectionInfoTh">Selectivity</th>
|
||||
<th class="collectionInfoTh">Fields</th>
|
||||
</tr>
|
||||
<%
|
||||
if (index){
|
||||
var fieldString = '';
|
||||
$.each(index.indexes, function(k,v) {
|
||||
$.each(index.indexes, function(k, v) {
|
||||
if (v.fields !== undefined) {
|
||||
fieldString = v.fields.join(", ");
|
||||
}
|
||||
|
@ -243,11 +244,17 @@
|
|||
//cut index id
|
||||
var position = v.id.indexOf('/');
|
||||
var indexId = v.id.substr(position+1, v.id.length);
|
||||
var selectivity = (
|
||||
v.hasOwnProperty("selectivityEstimate") ?
|
||||
(v.selectivityEstimate * 100).toFixed(1) + "%" :
|
||||
"n/a"
|
||||
);
|
||||
%>
|
||||
<tr>
|
||||
<th class="collectionInfoTh modal-text"><%=indexId%></th>
|
||||
<th class="collectionInfoTh modal-text"><%=v.type%></th>
|
||||
<th class="collectionInfoTh modal-text"><%=v.unique%></th>
|
||||
<th class="collectionInfoTh modal-text"><%=selectivity%></th>
|
||||
<th class="collectionInfoTh modal-text"><%=fieldString%></th>
|
||||
</tr>
|
||||
<%
|
||||
|
|
|
@ -222,10 +222,10 @@
|
|||
}
|
||||
|
||||
|
||||
if(collectionIsLoaded) {
|
||||
if (collectionIsLoaded) {
|
||||
// prevent "unexpected sync method error"
|
||||
var wfs = this.model.getProperties().waitForSync;
|
||||
tableContent.push(
|
||||
var wfs = this.model.getProperties().waitForSync;
|
||||
tableContent.push(
|
||||
window.modalView.createSelectEntry(
|
||||
"change-collection-sync",
|
||||
"Wait for sync",
|
||||
|
@ -263,7 +263,7 @@
|
|||
this.truncateCollection.bind(this)
|
||||
)
|
||||
);
|
||||
if(collectionIsLoaded) {
|
||||
if (collectionIsLoaded) {
|
||||
buttons.push(
|
||||
window.modalView.createNotificationButton(
|
||||
"Unload",
|
||||
|
|
|
@ -1095,7 +1095,7 @@
|
|||
var fieldString = '';
|
||||
var actionString = '';
|
||||
|
||||
$.each(this.index.indexes, function(k,v) {
|
||||
$.each(this.index.indexes, function(k, v) {
|
||||
if (v.type === 'primary' || v.type === 'edge') {
|
||||
actionString = '<span class="icon_arangodb_locked" ' +
|
||||
'data-original-title="No action"></span>';
|
||||
|
@ -1111,13 +1111,19 @@
|
|||
|
||||
//cut index id
|
||||
var position = v.id.indexOf('/');
|
||||
var indexId = v.id.substr(position+1, v.id.length);
|
||||
var indexId = v.id.substr(position + 1, v.id.length);
|
||||
var selectivity = (
|
||||
v.hasOwnProperty("selectivityEstimate") ?
|
||||
(v.selectivityEstimate * 100).toFixed(1) + "%" :
|
||||
"n/a"
|
||||
);
|
||||
|
||||
$('#collectionEditIndexTable').append(
|
||||
'<tr>'+
|
||||
'<th class=' + JSON.stringify(cssClass) + '>' + indexId + '</th>'+
|
||||
'<th class=' + JSON.stringify(cssClass) + '>' + v.type + '</th>'+
|
||||
'<th class=' + JSON.stringify(cssClass) + '>' + v.unique + '</th>'+
|
||||
'<th class=' + JSON.stringify(cssClass) + '>' + selectivity + '</th>'+
|
||||
'<th class=' + JSON.stringify(cssClass) + '>' + fieldString + '</th>'+
|
||||
'<th class=' + JSON.stringify(cssClass) + '>' + actionString + '</th>'+
|
||||
'</tr>'
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
/*global require, db, assertEqual, assertTrue */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the hash index, selectivity estimates
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var jsunity = require("jsunity");
|
||||
var internal = require("internal");
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- basic methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite: Creation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function HashIndexSuite() {
|
||||
var cn = "UnitTestsCollectionHash";
|
||||
var collection = null;
|
||||
|
||||
var sorter = function (l, r) {
|
||||
if (l.length != r.length) {
|
||||
return l.length - r.length < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
// length is equal
|
||||
for (i = 0; i < l.length; ++i) {
|
||||
if (l[i] != r[i]) {
|
||||
return l[i] < r[i] ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
internal.db._drop(cn);
|
||||
collection = internal.db._create(cn, { waitForSync : false });
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
// try...catch is necessary as some tests delete the collection itself!
|
||||
try {
|
||||
collection.unload();
|
||||
collection.drop();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
collection = null;
|
||||
internal.wait(0.0);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hash index selectivity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testSelectivityEstimateUnique : function () {
|
||||
var i;
|
||||
|
||||
var idx = collection.ensureUniqueConstraint("value");
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
collection.save({ _key: "test" + i, value: i });
|
||||
}
|
||||
|
||||
idx = collection.ensureUniqueConstraint("value");
|
||||
assertEqual(1, idx.selectivityEstimate);
|
||||
|
||||
for (i = 0; i < 50; ++i) {
|
||||
collection.remove("test" + i);
|
||||
}
|
||||
|
||||
idx = collection.ensureUniqueConstraint("value");
|
||||
assertEqual(1, idx.selectivityEstimate);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief multi hash index selectivity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testSelectivityEstimateNonUnique : function () {
|
||||
var i;
|
||||
|
||||
var idx = collection.ensureHashIndex("value");
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
collection.save({ value: i });
|
||||
}
|
||||
|
||||
idx = collection.ensureHashIndex("value");
|
||||
assertEqual(1, idx.selectivityEstimate);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
collection.save({ value: i });
|
||||
}
|
||||
|
||||
idx = collection.ensureHashIndex("value");
|
||||
assertTrue(idx.selectivityEstimate >= 0.45 && idx.selectivityEstimate <= 0.55);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
collection.save({ value: i });
|
||||
}
|
||||
|
||||
idx = collection.ensureHashIndex("value");
|
||||
assertTrue(idx.selectivityEstimate >= 0.3 && idx.selectivityEstimate <= 0.36);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief multi hash index selectivity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testSelectivityEstimateAllIdentical : function () {
|
||||
var i;
|
||||
|
||||
var idx = collection.ensureHashIndex("value");
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
collection.save({ value: 1 });
|
||||
}
|
||||
|
||||
idx = collection.ensureHashIndex("value");
|
||||
assertTrue(idx.selectivityEstimate <= (1 / 1000 + 0.0001));
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
collection.save({ value: 1 });
|
||||
}
|
||||
|
||||
idx = collection.ensureHashIndex("value");
|
||||
assertTrue(idx.selectivityEstimate <= (2 / 2000 + 0.0001));
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
collection.save({ value: 1 });
|
||||
}
|
||||
|
||||
idx = collection.ensureHashIndex("value");
|
||||
assertTrue(idx.selectivityEstimate <= (2 / 3000 + 0.0001));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- main
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suites
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(HashIndexSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -78,6 +78,8 @@ int TRI_InitMultiPointer (TRI_multi_pointer_t* array,
|
|||
array->_memoryZone = zone;
|
||||
array->_nrUsed = 0;
|
||||
array->_nrAlloc = 0;
|
||||
array->_nrUnique = 0;
|
||||
array->_nrDuplicate = 0;
|
||||
|
||||
if (nullptr == (array->_table_alloc = static_cast<TRI_multi_pointer_entry_t*>(TRI_Allocate(zone,
|
||||
sizeof(TRI_multi_pointer_entry_t) * INITIAL_SIZE + 64, true)))) {
|
||||
|
@ -374,6 +376,19 @@ size_t TRI_MemoryUsageMultiPointer (TRI_multi_pointer_t const* array) {
|
|||
return (size_t) array->_nrAlloc * sizeof(TRI_multi_pointer_entry_t) + 64;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a selectivity estimate of the index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
double TRI_SelectivityEstimateMultiPointer (TRI_multi_pointer_t const* array) {
|
||||
size_t numTotal = array->_nrUnique + array->_nrDuplicate;
|
||||
|
||||
if (numTotal == 0) {
|
||||
return 1.0;
|
||||
}
|
||||
return static_cast<double>(array->_nrUnique) / static_cast<double>(numTotal);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -416,6 +431,7 @@ void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t* array,
|
|||
array->_table[i].next = TRI_MULTI_POINTER_INVALID_INDEX;
|
||||
array->_table[i].prev = TRI_MULTI_POINTER_INVALID_INDEX;
|
||||
array->_nrUsed++;
|
||||
array->_nrUnique++;
|
||||
#ifdef TRI_CHECK_MULTI_POINTER_HASH
|
||||
TRI_CheckMultiPointerHash(array, true, true);
|
||||
#endif
|
||||
|
@ -442,6 +458,7 @@ void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t* array,
|
|||
array->_table[i].next = TRI_MULTI_POINTER_INVALID_INDEX;
|
||||
array->_table[i].prev = TRI_MULTI_POINTER_INVALID_INDEX;
|
||||
array->_nrUsed++;
|
||||
array->_nrUnique++;
|
||||
#ifdef TRI_CHECK_MULTI_POINTER_HASH
|
||||
TRI_CheckMultiPointerHash(array, true, true);
|
||||
#endif
|
||||
|
@ -489,6 +506,7 @@ void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t* array,
|
|||
array->_table[array->_table[j].next].prev = j;
|
||||
}
|
||||
array->_nrUsed++;
|
||||
array->_nrDuplicate++;
|
||||
|
||||
#ifdef TRI_CHECK_MULTI_POINTER_HASH
|
||||
TRI_CheckMultiPointerHash(array, true, true);
|
||||
|
@ -596,6 +614,7 @@ void* TRI_RemoveElementMultiPointer (TRI_multi_pointer_t* array, void const* ele
|
|||
TRI_CheckMultiPointerHash(array, false, false);
|
||||
#endif
|
||||
HealHole(array, i);
|
||||
array->_nrUnique--;
|
||||
}
|
||||
else {
|
||||
// There is at least one successor in position j.
|
||||
|
@ -605,6 +624,7 @@ void* TRI_RemoveElementMultiPointer (TRI_multi_pointer_t* array, void const* ele
|
|||
TRI_CheckMultiPointerHash(array, false, false);
|
||||
#endif
|
||||
HealHole(array, j);
|
||||
array->_nrDuplicate--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -621,6 +641,7 @@ void* TRI_RemoveElementMultiPointer (TRI_multi_pointer_t* array, void const* ele
|
|||
TRI_CheckMultiPointerHash(array, false, false);
|
||||
#endif
|
||||
HealHole(array, i);
|
||||
array->_nrDuplicate--;
|
||||
}
|
||||
array->_nrUsed--;
|
||||
#ifdef TRI_CHECK_MULTI_POINTER_HASH
|
||||
|
@ -679,11 +700,11 @@ static int ResizeMultiPointer (TRI_multi_pointer_t* array, size_t size) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_ResizeMultiPointer (TRI_multi_pointer_t* array, size_t size) {
|
||||
if (2*size+1 < array->_nrUsed) {
|
||||
if (2 * size + 1 < array->_nrUsed) {
|
||||
return TRI_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
return ResizeMultiPointer(array, 2*size+1);
|
||||
return ResizeMultiPointer(array, 2 * size + 1);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -112,6 +112,8 @@ typedef struct TRI_multi_pointer_s {
|
|||
|
||||
uint64_t _nrAlloc; // the size of the table
|
||||
uint64_t _nrUsed; // the number of used entries
|
||||
uint64_t _nrUnique; // number of unique entries
|
||||
uint64_t _nrDuplicate; // number of duplicate entries
|
||||
|
||||
TRI_multi_pointer_entry_t* _table_alloc; // the table itself
|
||||
TRI_multi_pointer_entry_t* _table; // the table itself, 64 aligned
|
||||
|
@ -175,6 +177,12 @@ void TRI_FreeMultiPointer (TRI_memory_zone_t*, TRI_multi_pointer_t*);
|
|||
|
||||
size_t TRI_MemoryUsageMultiPointer (TRI_multi_pointer_t const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a selectivity estimate for the index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
double TRI_SelectivityEstimateMultiPointer (TRI_multi_pointer_t const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -211,6 +219,7 @@ void* TRI_RemoveElementMultiPointer (TRI_multi_pointer_t*, void const* element);
|
|||
|
||||
int TRI_ResizeMultiPointer (TRI_multi_pointer_t*, size_t);
|
||||
|
||||
#if 0
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- MULTI ASSOCIATIVE POINTERS WITH MULTIPLE KEYS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -393,6 +402,7 @@ void* TRI_RemovePairMultiPair (TRI_multi_pair_t*,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_ResizeMultiPair (TRI_multi_pair_t*, size_t);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue