Skip to content

Commit 6c78e10

Browse files
authored
[Issue pixelsdb#1284] implement RocksDB index re-sharding (pixelsdb#1298)
The index can be sharded independently from the table data.
1 parent c37b350 commit 6c78e10

File tree

8 files changed

+458
-327
lines changed

8 files changed

+458
-327
lines changed

pixels-cli/src/main/java/io/pixelsdb/pixels/cli/executor/StatExecutor.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,16 @@ public void execute(Namespace ns, String command) throws Exception
166166
{
167167
for (Column column : columns)
168168
{
169-
String sql = "SELECT COUNT(DISTINCT(" + column.getName() + ")) AS cardinality, " +
170-
"SUM(CASE WHEN " + column.getName() + " IS NULL THEN 1 ELSE 0 END) AS null_count " +
171-
"FROM " + schemaName + "." + tableName;
169+
// ANSI SQL uses double quotes for identifiers.
170+
String sql = String.format(
171+
"SELECT COUNT(DISTINCT(\"%s\")) AS cardinality, " +
172+
"SUM(CASE WHEN \"%s\" IS NULL THEN 1 ELSE 0 END) AS null_count " +
173+
"FROM \"%s\".\"%s\"",
174+
column.getName(),
175+
column.getName(),
176+
schemaName,
177+
tableName
178+
);
172179
Statement statement = connection.createStatement();
173180
ResultSet resultSet = statement.executeQuery(sql);
174181
if (resultSet.next())

pixels-cli/src/main/java/io/pixelsdb/pixels/cli/load/IndexedPixelsConsumer.java

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import io.pixelsdb.pixels.common.physical.StorageFactory;
3636
import io.pixelsdb.pixels.common.utils.ConfigFactory;
3737
import io.pixelsdb.pixels.common.utils.DateUtil;
38+
import io.pixelsdb.pixels.common.utils.IndexUtils;
3839
import io.pixelsdb.pixels.common.utils.RetinaUtils;
3940
import io.pixelsdb.pixels.core.PixelsWriter;
4041
import io.pixelsdb.pixels.core.TypeDescription;
@@ -101,14 +102,14 @@ protected void processSourceFile(String originalFilePath) throws IOException, Me
101102

102103
// 1. Calculate Primary Key and Bucket ID
103104
ByteString pkByteString = calculatePrimaryKeyBytes(colsInLine);
104-
// Assume BucketCache has the necessary method and configuration
105-
int bucketId = RetinaUtils.getBucketIdFromByteBuffer(pkByteString);
106-
VnodeIdentifier vnodeIdentifier = RetinaUtils.getInstance().getVnodeIdentifierFromBucketId(bucketId);
105+
int retinaBucketId = RetinaUtils.getBucketIdFromByteBuffer(pkByteString);
106+
VnodeIdentifier vnodeIdentifier = RetinaUtils.getInstance().getVnodeIdentifierFromBucketId(retinaBucketId);
107+
int indexBucketId = IndexUtils.getBucketIdFromByteBuffer(pkByteString);
107108
PerVirtualNodeWriter retinaNodeWriter = retinaWriters.computeIfAbsent(vnodeIdentifier, id ->
108109
{
109110
try
110111
{
111-
return initializeRetinaWriter(bucketId);
112+
return initializeRetinaWriter(retinaBucketId);
112113
} catch (Exception e)
113114
{
114115
throw new RuntimeException("Failed to initialize writer for bucket " + id, e);
@@ -122,7 +123,7 @@ protected void processSourceFile(String originalFilePath) throws IOException, Me
122123
try
123124
{
124125
// 4. Update Index Entry
125-
updateIndexEntry(retinaNodeWriter, pkByteString);
126+
updateIndexEntry(retinaNodeWriter, pkByteString, indexBucketId);
126127

127128
// 5. Check and Flush Row Batch
128129
if (retinaNodeWriter.rowBatch.size >= retinaNodeWriter.rowBatch.getMaxSize())
@@ -222,7 +223,7 @@ private ByteString calculatePrimaryKeyBytes(String[] colsInLine)
222223
return ByteString.copyFrom((ByteBuffer) indexKeyBuffer.rewind());
223224
}
224225

225-
private void updateIndexEntry(PerVirtualNodeWriter bucketWriter, ByteString pkByteString) throws IndexException
226+
private void updateIndexEntry(PerVirtualNodeWriter bucketWriter, ByteString pkByteString, int indexBucketId) throws IndexException
226227
{
227228
IndexProto.PrimaryIndexEntry.Builder builder = IndexProto.PrimaryIndexEntry.newBuilder();
228229
builder.getIndexKeyBuilder()
@@ -237,7 +238,7 @@ private void updateIndexEntry(PerVirtualNodeWriter bucketWriter, ByteString pkBy
237238
.setFileId(bucketWriter.currFile.getId())
238239
.setRgRowOffset(bucketWriter.rgRowOffset++);
239240

240-
bucketWriter.indexEntries.add(builder.build());
241+
bucketWriter.indexBucketQueues[indexBucketId].add(builder.build());
241242
}
242243

243244
private void flushRowBatch(PerVirtualNodeWriter bucketWriter) throws IOException, IndexException
@@ -252,10 +253,18 @@ private void flushRowBatch(PerVirtualNodeWriter bucketWriter) throws IOException
252253
bucketWriter.prevRgId = bucketWriter.rgId;
253254
}
254255

255-
// Push index entries to the corresponding IndexService (determined by targetNode address)
256-
bucketWriter.indexService.putPrimaryIndexEntries(index.getTableId(), index.getId(), bucketWriter.indexEntries, bucketWriter.option);
257-
bucketWriter.indexService.flushIndexEntriesOfFile(index.getTableId(), index.getId(),bucketWriter.currFile.getId(), true, bucketWriter.option);
258-
bucketWriter.indexEntries.clear();
256+
for (int i = 0; i < bucketWriter.totalBuckets; i++)
257+
{
258+
List<IndexProto.PrimaryIndexEntry> queue = bucketWriter.indexBucketQueues[i];
259+
if (!queue.isEmpty())
260+
{
261+
IndexOption option = bucketWriter.indexOptions[i];
262+
bucketWriter.indexService.putPrimaryIndexEntries(index.getTableId(), index.getId(), queue, option);
263+
queue.clear();
264+
}
265+
}
266+
bucketWriter.indexService.flushIndexEntriesOfFile(index.getTableId(), index.getId(),
267+
bucketWriter.currFile.getId(), true, bucketWriter.defaultIndexOption);
259268
}
260269

261270
private void closePixelsFile(PerVirtualNodeWriter bucketWriter) throws IOException, IndexException
@@ -279,13 +288,16 @@ private class PerVirtualNodeWriter
279288
int prevRgId;
280289
int rowCounter;
281290
int vNodeId;
282-
IndexOption option;
283291
NodeProto.NodeInfo targetNode;
284-
List<IndexProto.PrimaryIndexEntry> indexEntries = new ArrayList<>();
285292
VectorizedRowBatch rowBatch;
286293
IndexService indexService;
287294
RowIdAllocator rowIdAllocator;
288295

296+
private final IndexOption defaultIndexOption;
297+
private final int totalBuckets;
298+
private final List<IndexProto.PrimaryIndexEntry>[] indexBucketQueues;
299+
private final IndexOption[] indexOptions;
300+
289301
public PerVirtualNodeWriter(PixelsWriter writer, File file, Path path, NodeProto.NodeInfo node, int vNodeId)
290302
{
291303
this.pixelsWriter = writer;
@@ -301,15 +313,17 @@ public PerVirtualNodeWriter(PixelsWriter writer, File file, Path path, NodeProto
301313
this.indexService = indexServices.computeIfAbsent(node.getAddress(), nodeInfo ->
302314
RPCIndexService.CreateInstance(nodeInfo, indexServerPort));
303315
this.rowIdAllocator = new RowIdAllocator(index.getTableId(), maxRowNum, this.indexService);
304-
initIndexOption();
305-
}
306-
307-
private void initIndexOption()
308-
{
309-
this.option = IndexOption.builder()
310-
.vNodeId(this.vNodeId)
311-
.build();
316+
this.totalBuckets = IndexUtils.getInstance().getBucketNum();
317+
this.indexBucketQueues = new List[totalBuckets];
318+
this.indexOptions = new IndexOption[totalBuckets];
319+
this.defaultIndexOption = new IndexOption();
320+
for (int i = 0; i < totalBuckets; i++)
321+
{
322+
this.indexBucketQueues[i] = new ArrayList<>();
323+
this.indexOptions[i] = IndexOption.builder()
324+
.vNodeId(i)
325+
.build();
326+
}
312327
}
313-
314328
}
315329
}

pixels-common/src/main/java/io/pixelsdb/pixels/common/utils/IndexUtils.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
package io.pixelsdb.pixels.common.utils;
2222

23+
import com.google.common.hash.Hashing;
24+
import com.google.protobuf.ByteString;
2325
import io.pixelsdb.pixels.common.exception.MetadataException;
2426
import io.pixelsdb.pixels.common.metadata.MetadataService;
2527
import io.pixelsdb.pixels.common.metadata.domain.Column;
@@ -34,6 +36,29 @@
3436
public class IndexUtils
3537
{
3638
private static final MetadataService metadataService = MetadataService.Instance();
39+
private static volatile IndexUtils instance;
40+
private final int bucketNum;
41+
42+
private IndexUtils()
43+
{
44+
ConfigFactory config = ConfigFactory.Instance();
45+
this.bucketNum = Integer.parseInt(config.getProperty("index.bucket.num"));
46+
}
47+
48+
public static IndexUtils getInstance()
49+
{
50+
if (instance == null)
51+
{
52+
synchronized (IndexUtils.class)
53+
{
54+
if (instance == null)
55+
{
56+
instance = new IndexUtils();
57+
}
58+
}
59+
}
60+
return instance;
61+
}
3762

3863
public static List<Column> extractInfoFromIndex(long tableId, long indexId) throws MetadataException
3964
{
@@ -65,4 +90,22 @@ public static List<Column> extractInfoFromIndex(String dbName, String tableName,
6590
}
6691
return orderedKeyCols;
6792
}
93+
94+
public static int getBucketIdFromByteBuffer(ByteString byteString)
95+
{
96+
IndexUtils indexUtils = IndexUtils.getInstance();
97+
98+
int hash = Hashing.sha256()
99+
.hashBytes(byteString.toByteArray())
100+
.asInt();
101+
102+
int absHash = Math.abs(hash);
103+
104+
return absHash % indexUtils.getBucketNum();
105+
}
106+
107+
public int getBucketNum()
108+
{
109+
return bucketNum;
110+
}
68111
}

pixels-common/src/main/resources/pixels.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ index.cache.capacity=10000000
372372
index.cache.expiration.seconds=3600
373373
# whether each index corresponds to its own column family
374374
index.rocksdb.multicf=false
375+
index.bucket.num=128
375376
# the directory where the sqlite files of main index are stored, each main index is stored as a sqlite file
376377
index.sqlite.path=/tmp/sqlite
377378
index.main.cache.bucket.num=7

0 commit comments

Comments
 (0)