Skip to content

Commit 2368e93

Browse files
committed
Improve locking iterator performance
Issue: locking iterator is several times slower than the default iterator in queries based on secondary keys. For example: select COUNT(*) from sbtest1 where k % 10 = 1 for update; This query ends up iterating over the entire table, and in the end locks the entire table, but does so by lots of small locks and seeks every time. This diff shows that by simply locking the entire table instead we can improve the performance of the iterator by 50% - it's still slower than the default implementation, but now it's much closer to it. This modification of course results in overlocking in queries such as select COUNT(*) from sbtest1 where k % 10 = 1 for update limit 3000; where instead of locking only a few thousands records, with this change we lock the entire table instead. This change is in this form a proof of concept, for a real patch I think we could go in two directions: * instead of a hard coded value, make this an adjustable session variable * or instead of simply stopping after a threshold, continue locking in linear or exponential batches
1 parent 4a9df3b commit 2368e93

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

storage/rocksdb/rdb_locking_iter.cc

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
/* This C++ file's header file */
99
#include "./rdb_locking_iter.h"
1010

11+
static const ulonglong max_lock_count = 1000;
12+
1113
namespace myrocks {
1214

1315
rocksdb::Iterator* GetLockingIterator(
@@ -119,11 +121,12 @@ void LockingIterator::lock_up_to(bool scan_forward,
119121
m_have_locked_until= true;
120122
m_locked_until.assign(end_key.data(), end_key.size());
121123
if (m_lock_count) (*m_lock_count)++;
124+
m_self_lock_count++;
122125
}
123126
}
124127

125128
/*
126-
Lock the range from target till the iterator end point that we are scaning
129+
Lock the range from target till the iterator end point that we are scanning
127130
towards. If there's no iterator bound, use index start (or end, depending
128131
on the scan direction)
129132
*/
@@ -141,7 +144,7 @@ void LockingIterator::lock_till_iterator_end(bool scan_forward,
141144
else
142145
m_kd->get_supremum_key(buf, &size);
143146

144-
DBUG_ASSERT(size == Rdb_key_def::INDEX_NUMBER_SIZE);
147+
assert(size == Rdb_key_def::INDEX_NUMBER_SIZE);
145148
end = rocksdb::Slice((const char*)buf, size);
146149
}
147150
} else {
@@ -153,7 +156,7 @@ void LockingIterator::lock_till_iterator_end(bool scan_forward,
153156
else
154157
m_kd->get_infimum_key(buf, &size);
155158

156-
DBUG_ASSERT(size == Rdb_key_def::INDEX_NUMBER_SIZE);
159+
assert(size == Rdb_key_def::INDEX_NUMBER_SIZE);
157160
end = rocksdb::Slice((const char*)buf, size);
158161
}
159162
}
@@ -171,6 +174,8 @@ void LockingIterator::lock_till_iterator_end(bool scan_forward,
171174
*/
172175
void LockingIterator::Scan(bool scan_forward,
173176
const rocksdb::Slice& target, bool call_next) {
177+
178+
174179
if (!m_iter->Valid()) {
175180
m_status = m_iter->status();
176181
m_valid = false;
@@ -180,6 +185,10 @@ void LockingIterator::Scan(bool scan_forward,
180185
}
181186
return;
182187
}
188+
if (m_self_lock_count > max_lock_count) {
189+
// already locked the entire index instead
190+
return;
191+
}
183192

184193
while (1) {
185194

@@ -197,11 +206,19 @@ void LockingIterator::Scan(bool scan_forward,
197206
auto end_key = m_iter->key();
198207
std::string end_key_copy= end_key.ToString();
199208

200-
lock_up_to(scan_forward, target, end_key);
201-
if (!m_status.ok()) {
202-
// Failed to get a lock (most likely lock wait timeout)
203-
m_valid = false;
204-
return;
209+
if (m_self_lock_count == max_lock_count)
210+
{
211+
// we can't handle too many small locks, just lock everything
212+
lock_till_iterator_end(scan_forward, target);
213+
}
214+
if (m_self_lock_count < max_lock_count)
215+
{
216+
lock_up_to(scan_forward, target, end_key);
217+
if (!m_status.ok()) {
218+
// Failed to get a lock (most likely lock wait timeout)
219+
m_valid = false;
220+
return;
221+
}
205222
}
206223

207224
//Ok, now we have a lock which is inhibiting modifications in the range
@@ -265,7 +282,7 @@ void LockingIterator::Scan(bool scan_forward,
265282
*/
266283

267284
void LockingIterator::SeekToFirst() {
268-
DBUG_ASSERT(0);
285+
assert(0);
269286
m_status = rocksdb::Status::NotSupported("Not implemented");
270287
m_valid = false;
271288
}
@@ -276,7 +293,7 @@ void LockingIterator::SeekToFirst() {
276293
*/
277294

278295
void LockingIterator::SeekToLast() {
279-
DBUG_ASSERT(0);
296+
assert(0);
280297
m_status = rocksdb::Status::NotSupported("Not implemented");
281298
m_valid = false;
282299
}

storage/rocksdb/rdb_locking_iter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class LockingIterator : public rocksdb::Iterator {
4242
bool m_valid;
4343

4444
ulonglong *m_lock_count;
45+
ulonglong m_self_lock_count = 0;
4546

4647
// If true, m_locked_until has a valid key value.
4748
bool m_have_locked_until;

0 commit comments

Comments
 (0)