I came across an interesting problem recently in some JDBC code that was inserting rows into a Netezza database.
The Java code was doing something like this:
Statement stmt ...
for( SomeObject o : listOfObjects) {
String sql = "INSERT INTO tbl(col1, col2) values (?,?)";
...
stmt.addBatch(sql);
}
stmt.executeBatch();
On the “executeBatch()”, a SQLException was being thrown that said “failed to create external table for bulk load”.
What? But it wasn’t a bulk load. There were no external tables involved - it was a batch of vanilla inserts.
In an attempt to debug the problem, I tried executing the statements inside the loop. No problem. It worked fine. The SQL was only a problem when executed as a batch.
So I opened up a PuTTY session and logged into the Netezza box and tailed the logs.
This is an excerpt from the NZ log file (found in /nz/kit.7.1.0.0/log/postgres/pg.log, for the curious).
2014-11-28 13:00:18.222493 EST [17672] DEBUG: QUERY: drop table bulkETL_17672_0
2014-11-28 13:00:18.232294 EST [17672] DEBUG: QUERY: CREATE EXTERNAL TABLE bulkETL_17672_0 ( c0 nvarchar(5),c1 nvarchar(48),c2 nvarchar(48),c3 nvarchar(6),c4 nvarchar(5),c5 nvarchar(5),c6 nvarchar(1),c7 nvarchar(2),c8 nvarchar(2) ) USING ( DATAOBJECT('/tmp/junk') REMOTESOURCE 'jdbc' DELIMITER ' ' ESCAPECHAR '\' CTRLCHARS 'YES' CRINSTRING 'YES' ENCODING 'INTERNAL' MAXERRORS 1 QUOTEDVALUE 'YES' );
2014-11-28 13:00:18.232295 EST [17672] ERROR: create external table: permission denied
So it seems that Netezza is optimizing my individual batch inserts, and executing them by writing the data to a file on disk and bulk-loading that file using an external table. This is a seemingly obvious optimization, since Netezza is really fast at performing bulk operations, and that it isn’t so good at single-row operations. In fact, it takes about the same amount of time to insert a single row as it does to insert a million rows.
The problem is that my userid didn’t have permissions to create an external table. The application userid can only perform basic SQL operations: SELECT, INSERT and UPDATE. So I get a permission denied error even though I’m trying to perform an INSERT - an operation that I have permission to do.
Granting the “create external table” permission fixed the problem, but it isn’t an ideal solution. I shouldn’t require permission to create an external table when all I want to do is insert a couple of rows.