Repository navigation
Conversation
69fcab9 to
4eec351
Compare
ericm-db
left a comment
There was a problem hiding this comment.
Only nits, most points were addressed on the previous PR.
4eec351 to
2a0602c
Compare
d358120 to
fa137f8
Compare
fa137f8 to
25e2230
Compare
25e2230 to
e259dd4
Compare
There was a problem hiding this comment.
maybe move arguments to new lines ?
There was a problem hiding this comment.
nit: the first argument does not seem to be moved
1f943d5 to
68186c4
Compare
68186c4 to
dffe870
Compare
a0c6457 to
2e346de
Compare
6a4b641 to
9e7750f
Compare
HeartSaVioR
left a comment
There was a problem hiding this comment.
First pass. Looks OK in general. Will have a second review once we merge the PR #45038 and this PR is rebased.
| StateStoreProvider.createAndInit( | ||
| stateStoreProviderId, keySchema, valueSchema, numColsPrefixKey, | ||
| useColumnFamilies = false, storeConf, hadoopConf.value) | ||
| useColumnFamilies = false, storeConf, hadoopConf.value, useMultipleValuesPerKey = false) |
There was a problem hiding this comment.
Shall we file a JIRA ticket to support transformWithState with state data source - reader? From what I understand, we are deferring on supporting this. Please correct me if I'm missing.
There was a problem hiding this comment.
I think we already have this planned. @anishshri-db Do we have the JIRA created for this support?
There was a problem hiding this comment.
Filed the ticket here - https://issues.apache.org/jira/browse/SPARK-47047
There was a problem hiding this comment.
nit: the first argument does not seem to be moved
| class ListStateImpl[S](store: StateStore, | ||
| stateName: String, | ||
| keyExprEnc: ExpressionEncoder[Any]) | ||
| extends ListState[S] with Logging { |
There was a problem hiding this comment.
I think you can create serializer from keyExprEnc here as field and pass serializer instead in encodeGroupingKey.
| val keyByteArr = toRow | ||
| .apply(keyOption.get).asInstanceOf[UnsafeRow].getBytes() | ||
|
|
||
| val keyEncoder = UnsafeProjection.create(KEY_ROW_SCHEMA) |
There was a problem hiding this comment.
If we are fully sure we will end up with binary key - binary value for every state type, this should go up to fields in this object. Same for valueEncoder. If we anticipate different schema, maybe keyEncoder / valueEncoder should be passed as parameter instead.
There was a problem hiding this comment.
We do not anticipate a different schema. Every key, value will be encoded to a byte Array. While working on refactoring key/value Encoder to move them to object level, I discovered that UnsafeProjection is not thread safe. Hence, we cannot use it across state variables.
Refactored this logic to create a class instead of utils object, and the class instance is not shared across state variables.
| def remove(key: UnsafeRow, | ||
| colFamilyName: String = StateStore.DEFAULT_COL_FAMILY_NAME): Unit | ||
|
|
||
| def merge(key: UnsafeRow, value: UnsafeRow, |
There was a problem hiding this comment.
Shall we add method doc?
There was a problem hiding this comment.
Sorry, missed the doc here. Added.
092c75a to
00183db
Compare
HeartSaVioR
left a comment
There was a problem hiding this comment.
Only details and optional comments.
There was a problem hiding this comment.
Thinking out loud - it'd be ideal if we can move out the context of schema for state store key/value entirely to StateTypesEncoderUtils. State impls don't need to know about anything except that StateTypesEncoderUtils will give the UnsafeRow, and all context about serde will be put to StateTypesEncoderUtils. Just a 2 cents, not mandatory to address.
There was a problem hiding this comment.
If we anticipate further changes to StateTypesEncoderUtils it's also OK to leave it as it is and make such change in later phase.
There was a problem hiding this comment.
This schema is currently used in TransformWithStateExec operator to create the StateStoreRDD, in the state variables to create RocksDB column family, and inside the EncoderUtils for serde. We can unify the last 2 easily, and that way state impl classes would not need to know about the schema. It would be better to make this change with MapState finalized as that class will modify the stateTypesEncoder. Let me know if that sounds good.
There was a problem hiding this comment.
Yeah we can defer to the later phase - it may give better visibility upon further changes.
There was a problem hiding this comment.
I know this is beyond the scope of PR, but while we are here, I don't see any difference with Option(get()).
There was a problem hiding this comment.
This triggers overhead so we wouldn't like to do this for every value. Either we have to sample (that's why we only do for the first value) or not doing this at all. It's probably OK to do latter as get() also doesn't do this for the case where there are multiple CFs.
There was a problem hiding this comment.
Removed the wrapper iterator, we don't need it anymore. Thanks for pointing this out.
There was a problem hiding this comment.
Let's make a contract about expected return value, especially about clarification of value for non-existing key. Multiple implementations should follow the contract so this needs to be clearly explained.
There was a problem hiding this comment.
Maybe we want to explicitly document the contract on the behavior when performing merge against non-existing key, since all implementations should provide the same.
41dc298 to
ebd9895
Compare
There was a problem hiding this comment.
I talked offline but to leave record (and not forget) -
The overhead of creating UnsafeProjection is significant and we really need to reuse this, with keeping in mind that the instance returned from UnsafeProjecion.create() would be thread-unsafe. So we should either 1) use thread-local or 2) just change this object (singleton) into class and initialize per state impl.
Aggressively you can even create it in operator-partition level so that multiple state impls can share without worrying about thread-safety (benefit of 1) but even without thread-local), but maybe it won't be a significant gain.
There was a problem hiding this comment.
Thanks for pointing out the overhead of UnsafeProjection. I changed the StateTypesEncoderUtils to a class and its initialized per state impl to reuse the UnsafeProjection (for a StateImpl).
c6066d0 to
880b0ba
Compare
880b0ba to
92c263d
Compare
|
CI failed from Run / Build modules: pyspark-sql, pyspark-resource, pyspark-testing but none of test failures are relevant to this change. |
|
Thanks! Merging to master. |
### What changes were proposed in this pull request? The pr aims to remove some unused error classes, include: - _LEGACY_ERROR_TEMP_3193: The code in PR(#44961) no longer uses this error class, but the related item in the file `error-classes.json` has not been deleted synchronously. - _LEGACY_ERROR_TEMP_3197: The code in PR(#44961) no longer uses this error class, but the related item in the file `error-classes.json` has not been deleted synchronously. - _LEGACY_ERROR_TEMP_3234: This should be the follow-up work of #44665 - STATE_STORE_MULTIPLE_VALUES_PER_KEY: Introduced by [SPARK-46864](#44883), but not actually used in codebase. - TWS_VALUE_SHOULD_NOT_BE_NULL: Introduced by [SPARK-46864](#44883), but not actually used in codebase. ### Why are the changes needed? Make the code cleaner. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? - Pass GA. - Manually check. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #45509 from panbingkun/remove_outdated_error_classes. Authored-by: panbingkun <panbingkun@baidu.com> Signed-off-by: Max Gekk <max.gekk@gmail.com>
What changes were proposed in this pull request?
This PR adds changes for ListState implementation in State Api v2. As a list contains multiple values for a single key, we utilize RocksDB merge operator to persist multiple values.
Changes include
Why are the changes needed?
These changes are needed to support list values in the State Store. The changes are part of the work around adding new stateful streaming operator for arbitrary state mgmt that provides a bunch of new features listed in the SPIP JIRA here - https://issues.apache.org/jira/browse/SPARK-45939
Does this PR introduce any user-facing change?
Yes
This PR introduces a new state type (ListState) that users can use in their Spark streaming queries.
How was this patch tested?
Was this patch authored or co-authored using generative AI tooling?
No