FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(spanner): add lazy decode to partitioned query by sinhasubham · Pull Request #1411 · googleapis/python-spanner · GitHub

This repository was archived by the owner on Jun 8, 2026. It is now read-only.
/ python-spanner Public archive

feat(spanner): add lazy decode to partitioned query - #1411

Merged
sinhasubham merged 2 commits into
mainfrom
gilContentionLazy
Oct 9, 2025
Merged

feat(spanner): add lazy decode to partitioned query#1411
sinhasubham merged 2 commits into
mainfrom
gilContentionLazy

Conversation

Copy link
Copy Markdown
Contributor

Add lazy decode to partitioned query

This commit introduces a lazy_decode option to BatchSnapshot.run_partitioned_query. When set to True, the result set yields raw protobuf objects instead of decoded Python objects.

This allows the CPU-intensive decoding work to be deferred and managed by the caller, which can significantly improve performance in multi-threaded applications by reducing GIL contention.

To support this, MergedResultSet now includes decode_row() and decode_column() methods for manual decoding of results.

product-auto-label Bot added size: m Pull request size is medium. api: spanner Issues related to the googleapis/python-spanner API. labels Sep 16, 2025
sinhasubham marked this pull request as ready for review September 23, 2025 11:42
sinhasubham requested review from a team September 23, 2025 11:42
*,
retry=gapic_v1.method.DEFAULT,
timeout=gapic_v1.method.DEFAULT,
lazy_decode=False,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

nit: add documentation for this new argument

Comment thread tests/unit/test_merged_result_set.py Outdated
@@ -0,0 +1,128 @@
# Copyright 2024 Google LLC All rights reserved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

nit: 2025

Comment on lines +156 to +191
def decode_row(self, row: []) -> []:
"""Decodes a row from protobuf values to Python objects. This function
should only be called for result sets that use ``lazy_decoding=True``.
The array that is returned by this function is the same as the array
that would have been returned by the rows iterator if ``lazy_decoding=False``.

:returns: an array containing the decoded values of all the columns in the given row
"""
if not isinstance(row, (list, tuple)):
raise TypeError("row must be an array of protobuf values")
decoders = self._decoders
return [
_parse_nullable(row[index], decoders[index]) for index in range(len(row))
]

def decode_column(self, row: [], column_index: int):
"""Decodes a column from a protobuf value to a Python object. This function
should only be called for result sets that use ``lazy_decoding=True``.
The object that is returned by this function is the same as the object
that would have been returned by the rows iterator if ``lazy_decoding=False``.

:returns: the decoded column value
"""
if not isinstance(row, (list, tuple)):
raise TypeError("row must be an array of protobuf values")
decoders = self._decoders
return _parse_nullable(row[column_index], decoders[column_index])

@property
def _decoders(self):
if self.metadata is None:
raise ValueError("iterator not started")
return [
_get_type_decoder(field.type_, field.name, None)
for field in self.metadata.row_type.fields
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Is this code really needed? A MergedResultSet just delegates all underlying logic to the 'normal' ResultSets. Those already support lazy decoding. So could we not just call the decode_row/decode_column function of one of the underlying ResultSets instead?

"""
if not isinstance(row, (list, tuple)):
raise TypeError("row must be an array of protobuf values")
decoders = self._decoders

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Can we cache this instead of reconstructing it for every row?

sinhasubham enabled auto-merge (squash) October 9, 2025 10:26
sinhasubham merged commit a09961b into main Oct 9, 2025
21 of 23 checks passed
sinhasubham deleted the gilContentionLazy branch October 9, 2025 10:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

api: spanner Issues related to the googleapis/python-spanner API. size: m Pull request size is medium.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants


Back | FazBrowse Home | New Git URL