On 1/31/07, Tom Lane <[EMAIL PROTECTED]> wrote:
"Pavan Deolasee" <[EMAIL PROTECTED]> writes: > Btw, I noticed that the toast_insert_or_update() is re-entrant. > toast_save_datum() calls simple_heap_insert() which somewhere down the > line calls toast_insert_or_update() again. The toast code takes pains to ensure that the tuples it creates won't be subject to re-toasting. Else it'd be an infinite recursion.
I think I found it. The toast_insert_or_update() function gets into an unnecessary recursion because of alignment issues. It thus toasts already toasted data. This IMHO might be causing unnecessary overheads for each toast operation. The default value of TOAST_TUPLE_THRESHOLD is 2034 (assuming 8K block size) TOAST_MAX_CHUNK_SIZE is defined as below: #define TOAST_MAX_CHUNK_SIZE (TOAST_TUPLE_THRESHOLD - \ MAXALIGN( \ MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) + \ sizeof(Oid) + \ sizeof(int32) + \ VARHDRSZ)) So the default value of TOAST_MAX_CHUNK_SIZE is set to 1994. When toast_insert_or_update() returns a tuple for the first chunk, t_len is set to 2034 (TOAST_MAX_CHUNK_SIZE + tuple header + chunk_id + chunk_seqno + VARHDRSZ) In heap_insert(), we MAXALIGN(tup->t_len) before comparing it with TOAST_TUPLE_THRESHOLD to decide whether to invoke TOAST or not. In this corner case, MAXALIGN(2034) = 2036 > TOAST_TUPLE_THRESHOLD and so TOAST is invoked again. Fortunately, we don't get into infinite recursion because reltoastrelid is set to InvalidOid for toast tables and hence TOASTing is not invoked in the second call. Attached is a patch which would print the recursion depth for toast_insert_or_update() before PANICing the server to help us examine the core. Let me know if this sounds like an issue and I can work out a patch. Thanks, Pavan -- EnterpriseDB http://www.enterprisedb.com