Subject: | Updating a table with a CLOB field causes SQL to take 40 seconds to execute |
Date: | Mon, 18 Jul 2011 15:20:54 +0100 |
To: | bug-DBIx-Class [...] rt.cpan.org |
From: | Gareth Tunley <gjtunley [...] gmail.com> |
Hi,
I am trying to convert my code to use DBIx::Class instead of Class::DBI and
have hit the following issue.
I have a table defined in Oracle as follows:
CREATE TABLE transaction (
transaction_id VARCHAR2(50 BYTE),
time_started TIMESTAMP(6),
method_called VARCHAR2(50 BYTE),
input_parameters VARCHAR2(4000 BYTE),
return_value CLOB,
time_finished TIMESTAMP(6)
);
ALTER TABLE transaction ADD CONSTRAINT pk_transaction PRIMARY KEY
(transaction_id);
ALTER TABLE transaction ADD CONSTRAINT method_called_notnull CHECK
(method_called IS NOT NULL);
ALTER TABLE transaction ADD CONSTRAINT transaction_time_notnull CHECK
(time_started IS NOT NULL);
My code which inserts and selects rows works fine, but when I try to update
the table to populate the return_value and time_finished fields the SQL
executed takes over 40 seconds to run.
It only is affected when I do an update with the return_value column in the
update.
Here is the trace from DBIC_TRACE=1 (annotated by me with the lines
beginning with #):
# Connect to database and set timestamp format
ALTER SESSION SET NLS_TIMESTAMP_FORMAT='DD/MM/YYYY HH24:MI:SS.FF':
# Check the transaction id doesn't already exist
SELECT me.transaction_id, me.time_started, me.method_called,
me.input_parameters, me.time_finished, me.return_value FROM transaction me
WHERE ( me.transaction_id = ? ) : '10401-1310989565-79528'
# Create the transaction record
BEGIN WORK
INSERT INTO transaction ( input_parameters, method_called, time_started,
transaction_id) VALUES ( ?, ?, ?, ? ): '<opt method="status"
transactionid="10401-1310989565-79528" />', 'System->status', '18/07/2011
12:46:05.915440', '10401-1310989565-79528'
COMMIT
# ... do the actual work
# Find the transaction record to stop
SELECT me.transaction_id, me.time_started, me.method_called,
me.input_parameters, me.time_finished, me.return_value FROM transaction me
WHERE ( me.transaction_id = ? ) : '10401-1310989565-79528'
# Stop the transaction record
BEGIN WORK
UPDATE transaction SET return_value = ?, time_finished = ? WHERE ( (
UTL_RAW.CAST_TO_VARCHAR2(RAWTOHEX(DBMS_LOB.SUBSTR(transaction_id, 2000, 1)))
= ? ) ): '<opt resultCode="200" resultString="OK"
transactionid="10401-1310989565-79528" />', '18/07/2011 12:46:05.947700',
'10401-1310989565-79528'
COMMIT
If I switch to updating the time_finished and return_value columns
separately then I see:
# Connect to database and set timestamp format
ALTER SESSION SET NLS_TIMESTAMP_FORMAT='DD/MM/YYYY HH24:MI:SS.FF':
# Check the transaction id doesn't already exist
SELECT me.transaction_id, me.time_started, me.method_called,
me.input_parameters, me.time_finished, me.return_value FROM transaction me
WHERE ( me.transaction_id = ? ) : '8750-1310996465-76528'
# Create the transaction record
BEGIN WORK
INSERT INTO transaction ( input_parameters, method_called, time_started,
transaction_id) VALUES ( ?, ?, ?, ? ): '<opt method="status"
transactionid="8750-1310996465-76528" />
', 'System->status', '18/07/2011 14:41:05.962670', '8750-1310996465-76528'
COMMIT
# ... do the actual work
# Find the transaction record to stop
SELECT me.transaction_id, me.time_started, me.method_called,
me.input_parameters, me.time_finished, me.return_value FROM transaction me
WHERE ( me.transaction_id = ? ) : '8750-1310996465-76528'
# Set the time_finished - executes very quickly
BEGIN WORK
UPDATE transaction SET time_finished = ? WHERE ( transaction_id = ? ):
'18/07/2011 14:41:06.038030', '8750-1310996465-76528'
COMMIT
# Set the return_value - takes long time to execute
BEGIN WORK
UPDATE transaction SET return_value = ? WHERE ( (
UTL_RAW.CAST_TO_VARCHAR2(RAWTOHEX(DBMS_LOB.SUBSTR(transaction_id, 2000, 1)))
= ? ) ): '<opt resultCode="200" resultString="OK"
transactionid="8750-1310996465-76528" />', '8750-1310996465-76528'
COMMIT
Looking at the WHERE clause where the SQL takes a long time, it appears to
treating the transaction id as a LOB rather than the return_value column
which is the actual LOB value,
I am using Perl 5.14.0
DBIx::Class 0.08192
DBI 1.616
DBD::Oracle 1.28
Thanks
Gareth