-
Notifications
You must be signed in to change notification settings - Fork 994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PHOENIX-3547 Supporting more number of indices per table. #317
Conversation
Currently the number of indices per Phoenix table is bound to maximum of 65535 (java.lang.Short) which is a limitation for applications requiring to have unlimited number of indices. This change will consider any new table created in Phoenix to support view index ids to be in the range of -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (java.lang.Long) which is undoubtably big enough to cover this requirement. Any existing Phoenix table will still continue to support only maximum of 65535 of indices. A new boolean column (USE_LONG_VIEW_INDEX BOOLEAN DEFAULT FALSE) is added to SYSTEM.CATALOG to specify each Phoenix table's support for large number of indices. On each new Phoenix table creation the value for USE_LONG_VIEW_INDEX will be set to `true` while this value would be false for any existing table.
@@ -1223,7 +1225,9 @@ public void readFields(DataInput input) throws IOException { | |||
boolean hasViewIndexId = encodedIndexedColumnsAndViewId < 0; | |||
if (hasViewIndexId) { | |||
// Fixed length | |||
viewIndexId = new byte[MetaDataUtil.getViewIndexIdDataType().getByteSize()]; | |||
//Use leacy viewIndexIdType for clients older than 4.10 release |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: typo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -2185,7 +2223,7 @@ public void createTable(RpcController controller, CreateTableRequest request, | |||
throw sqlExceptions[0]; | |||
} | |||
long seqValue = seqValues[0]; | |||
if (seqValue > Short.MAX_VALUE) { | |||
if (seqValue > Long.MAX_VALUE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is no longer needed since the indexId is now a Long. When you call incrementSequences if the current sequence value is LONG.MAX_VALUE you will get an exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
private Long getViewIndexValue(PDataType type, byte[] range, PDataType viewIndexDataType){ | ||
boolean useLongViewIndex = MetaDataUtil.getViewIndexIdDataType().equals(viewIndexDataType); | ||
Object s = type.toObject(range); | ||
return (useLongViewIndex ? (Long) s : (Short) s) - (useLongViewIndex ? Long.MAX_VALUE : Short.MAX_VALUE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JamesRTaylor or @chrajeshbabu do you know if this change is correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the argument be all that's necessary? Why is an additional type argument needed? The type as defined in the schema should be the right type, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
private PDataType getViewIndexType(Cell[] tableKeyValues) { | ||
Cell useLongViewIndexKv = tableKeyValues[USE_LONG_VIEW_INDEX]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For existing tables the VIEW_INDEX_ID column will store the index as a short while for new tables the value will be stored as a long.
Would it be cleaner to create a new column that stores the view index id as a long. In QueryServicesConnectionImpl.upgradeSystemTables() we would set the new column based on the existing value. Finally we can remove the existing VIEW_INDEX_ID in the next release.
WDYT @JamesRTaylor ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to keep the single VIEW_INDEX_ID column and make sure it's type is defined (through a property) at create time (and not allow it to be changed). The issue isn't with the metadata, but with the row key of the rows of the table. In old tables, it'll be a short while for new tables it'll be a long. We don't want to have to rewrite the data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having a boolean add a column that represents the type of the view index id (VIEW_INDEX_ID_DATA_TYPE)
Thanks @twdsilva for the review and feed backs. |
Currently the number of indices per Phoenix table is bound to maximum of 65535 (java.lang.Short) which is a limitation for applications requiring to have unlimited number of indices. This change will consider any new table created in Phoenix to support view index ids to be in the range of -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (java.lang.Long) which is undoubtably big enough to cover this requirement. Any existing Phoenix table will still continue to support only maximum of 65535 of indices. A new boolean column (USE_LONG_VIEW_INDEX BOOLEAN DEFAULT FALSE) is added to SYSTEM.CATALOG to specify each Phoenix table's support for large number of indices. On each new Phoenix table creation the value for USE_LONG_VIEW_INDEX will be set to `true` while this value would be false for any existing table.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using a boolean to represent whether the view index id is a long or not use an int to represent the view index data type.
We need to handle an older client talking to a new server while a cluster is being upgraded. While changing the protobuf you need to ensure backward compatiblity is maintained.
/** | ||
* A designator for choosing the right type for viewIndex (Short vs Long) to be backward compatible. | ||
* **/ | ||
private static final KeyValue USE_LONG_VIEW_INDEX_ID_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, USE_LONG_VIEW_INDEX_BYTES); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using a boolean can you use an int to store the data type. You can do something similar to how the DATA_TYPE of a column is set.
Cell dataTypeKv = colKeyValues[DATA_TYPE_INDEX];
PDataType dataType =
PDataType.fromTypeId(PInteger.INSTANCE.getCodec().decodeInt(
dataTypeKv.getValueArray(), dataTypeKv.getValueOffset(), SortOrder.getDefault()));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
* @return | ||
*/ | ||
private Long decodeViewIndexId(Cell viewIndexIdKv, PDataType viewIndexType) { | ||
boolean useLongViewIndex = MetaDataUtil.getViewIndexIdDataType().equals(viewIndexType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just call getCodec().decodeLong() in both cases here.
} | ||
|
||
private PDataType getViewIndexType(Cell[] tableKeyValues) { | ||
Cell useLongViewIndexKv = tableKeyValues[USE_LONG_VIEW_INDEX]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having a boolean add a column that represents the type of the view index id (VIEW_INDEX_ID_DATA_TYPE)
if (proto.hasViewIndexId()) { | ||
result.viewIndexId = proto.getViewIndexId(); | ||
} | ||
result.viewIndexType = proto.hasUseLongViewIndexId() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change the boolean to use an int to represent the data type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -1340,6 +1344,9 @@ public static IndexMaintainer fromProto(ServerCachingProtos.IndexMaintainer prot | |||
maintainer.nIndexSaltBuckets = proto.getSaltBuckets(); | |||
maintainer.isMultiTenant = proto.getIsMultiTenant(); | |||
maintainer.viewIndexId = proto.hasViewIndexId() ? proto.getViewIndexId().toByteArray() : null; | |||
maintainer.viewIndexType = proto.hasUseLongViewIndex() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change to use data type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -75,7 +76,8 @@ message MetaDataResponse { | |||
repeated SharedTableState sharedTablesToDelete = 9; | |||
optional PSchema schema = 10; | |||
optional int64 autoPartitionNum = 11; | |||
optional int32 viewIndexId = 12; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot change the type of viewIndexId because we need to support an old client talking to a new server while a cluster is being upgraded. Add a new optional bytes field and file a JIRA to remove the viewIndexId field in the next release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@twdsilva Just for clarification. Do you mean to add a new column like
optional bytes viewIndexLongId = 13;
and then retire viewIndexId in the next version.
This make sense but I only don't understand why the new property cannot be a optional int64?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct the new property can be an optional int64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Thanks for quick response
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@twdsilva @JamesRTaylor
I just ran into this:
https://developers.google.com/protocol-buffers/docs/proto#updating
int32, uint32, int64, uint64, and bool are all compatible – this means you can change a field from one of these types to another without breaking forwards- or backwards-compatibility. If a number is parsed from the wire which doesn't fit in the corresponding type, you will get the same effect as if you had cast the number to that type in C++ (e.g. if a 64-bit number is read as an int32, it will be truncated to 32 bits)
If I understand it correctly, we can just add the indexType
column to the .proto wherever we have viewIndexId and change the viewIndexId
type from int32
to int64
without any side effect for old clients and hence we won't need to add viewIndexLongId
and PHOENIX-4838.
Am I missing anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the doc it looks like it should be ok to just change the viewIndexId type from int32 to int64.
We don't have a good way to test that this in a unit test. You could test that this works correctly manually by creating a view with the 4.14 server and client jar and then replacing the server jar with one that has your patch and verifying that you can still run queries against the view.
@@ -75,7 +76,8 @@ message MetaDataResponse { | |||
repeated SharedTableState sharedTablesToDelete = 9; | |||
optional PSchema schema = 10; | |||
optional int64 autoPartitionNum = 11; | |||
optional int32 viewIndexId = 12; | |||
optional int64 viewIndexId = 12; | |||
optional bool useLongViewIndexId = 13; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change from boolean to data type
@@ -85,7 +85,7 @@ message PTable { | |||
optional bytes viewStatement = 18; | |||
repeated bytes physicalNames = 19; | |||
optional bytes tenantId = 20; | |||
optional int32 viewIndexId = 21; | |||
optional int64 viewIndexId = 21; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as earlier, we need to support backward compatibility.
@@ -62,6 +62,7 @@ message IndexMaintainer { | |||
repeated ColumnInfo indexedColumnInfo = 19; | |||
required int32 encodingScheme = 20; | |||
required int32 immutableStorageScheme = 21; | |||
optional bool useLongViewIndex = 22; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change to data type
@@ -2285,6 +2317,7 @@ public void createTable(RpcController controller, CreateTableRequest request, | |||
builder.setReturnCode(MetaDataProtos.MutationCode.TABLE_NOT_FOUND); | |||
if (indexId != null) { | |||
builder.setViewIndexId(indexId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case the create table request was made from an older client you need to set the viewIndexId as an int32 (as thats what the client is expecting). See my other comment about maintaing backward compatibility.
Closes apache#318 Signed-off-by: Josh Elser <elserj@apache.org>
…ist to ASC sort order always
Currently the number of indices per Phoenix table is bound to maximum of 65535 (java.lang.Short) which is a limitation for applications requiring to have unlimited number of indices. This change will consider any new table created in Phoenix to support view index ids to be in the range of -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (java.lang.Long) which is undoubtably big enough to cover this requirement. Any existing Phoenix table will still continue to support only maximum of 65535 of indices. A new int column (VIEW_INDEX_ID_DATA_TYPE TINYINT) is added to SYSTEM.CATALOG to specify each Phoenix table's vewIndex data type. On each new Phoenix table creation the value for VIEW_INDEX_ID_DATA_TYPE will be set to `Long` while this value would be `Short` for any existing table.
moved to #324 |
Currently the number of indices per Phoenix table is bound to maximum of 65535 (java.lang.Short) which is a limitation for applications requiring to have unlimited number of indices.
This change will consider any new table created in Phoenix to support view index ids to be in the range of -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (java.lang.Long) which is undoubtably big enough to cover this requirement.
Any existing Phoenix table will still continue to support only maximum of 65535 of indices.
A new int column (VIEW_INDEX_ID_DATA_TYPE TINYINT) is added to SYSTEM.CATALOG to specify each Phoenix table's vewIndex data type.
On each new Phoenix table creation the value for VIEW_INDEX_ID_DATA_TYPE will be set to
Long
while this value would beShort
for any existing table.