github-actions[bot] commented on code in PR #41059:
URL: https://github.com/apache/beam/pull/41059#discussion_r4498085205


##########
sdks/python/apache_beam/io/gcp/bigquery.py:
##########
@@ -1522,6 +1523,25 @@ def BigQuerySink(*args, validate=False, **kwargs):
 
 
 _KNOWN_TABLES = set()
+_PRIMITIVE_SIZEOF_TYPES = (str, int, float, bool, bytes, type(None))
+
+
+def _fast_row_and_insert_id_size(row_and_insert_id):
+  if type(row_and_insert_id) is tuple and len(row_and_insert_id) == 2:
+    row, insert_id = row_and_insert_id
+    if type(row) is dict and type(insert_id) in _PRIMITIVE_SIZEOF_TYPES:
+      getsizeof = sys.getsizeof
+      total = getsizeof(row_and_insert_id) + getsizeof(row)
+      if insert_id is not None:
+        total += getsizeof(insert_id)
+      for k, v in row.items():
+        if not (type(k) in _PRIMITIVE_SIZEOF_TYPES and
+                type(v) in _PRIMITIVE_SIZEOF_TYPES):
+          return get_deep_size(row_and_insert_id)
+        total += getsizeof(k) + (

Review Comment:
   **🟡 Medium**: `objsize.get_deep_size` tracks visited object IDs so that 
objects referenced multiple times within the same row (e.g., multiple columns 
referencing the same string/bytes object, or cached/interned scalars like 
`True`/`False`, small `int`s, or `""`) are only counted once. Here, `v` is only 
deduplicated against `insert_id`, so if multiple keys in `row` share the same 
value reference (especially a large `str` or `bytes` object), `total` will 
count `sys.getsizeof(v)` multiple times. This could cause a row to be 
overestimated relative to `get_deep_size` and falsely exceed 
`_max_insert_payload_size` (routing valid rows to `FAILED_ROWS`).
   
   Consider either falling back to `get_deep_size` when `total >= 
max_insert_payload_size` in `_check_row_size` before rejecting a row, or 
tracking seen object IDs when needed.



##########
sdks/python/apache_beam/io/gcp/bigquery.py:
##########
@@ -1727,7 +1747,7 @@ def _create_table_if_needed(self, table_reference, 
schema=None):
 
   def _check_row_size(self, row_and_insert_id) -> tuple[int, Optional[str]]:
     """Returns error string when the row estimated size is too big"""
-    row_byte_size = get_deep_size(row_and_insert_id)
+    row_byte_size = _fast_row_and_insert_id_size(row_and_insert_id)

Review Comment:
   **🟡 Medium**: If `_fast_row_and_insert_id_size` overestimates a row due to 
shared object references across fields (which `get_deep_size` deduplicates), a 
row near the limit could be routed to the DLQ even though 
`get_deep_size(row_and_insert_id) < self._max_insert_payload_size`. Re-checking 
with `get_deep_size(row_and_insert_id)` inside the `if row_byte_size >= 
self._max_insert_payload_size:` branch would preserve exact 
backwards-compatible DLQ behavior at zero cost on the normal path.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to