Skip to content

Commit cc25727

Browse files
committedJun 1, 2018
[Postgres provider] Speed up feature insertion when pkid column is not set (fixes #18976)
When inserting features whose attribute column corresponding to the pkid is empty, and tat this pkid column has a default value using a sequence, then we can remove it from the INSERT statement completely, which save us from doing a SELECT nextval(...) for each row. On the provided test case of that ticket, on a debug build, this cuts down the insertion time from 5 minutes to 1 minute 10s.
1 parent bd65fc6 commit cc25727

File tree

1 file changed

+35
-7
lines changed

1 file changed

+35
-7
lines changed
 

‎src/providers/postgres/qgspostgresprovider.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,15 +2029,41 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist, Flags flags )
20292029
delim = ',';
20302030
}
20312031

2032-
if ( mPrimaryKeyType == PktInt || mPrimaryKeyType == PktFidMap || mPrimaryKeyType == PktUint64 )
2032+
// Optimization: if we have a single primary key column whose default value
2033+
// is a sequence, and that none of the features have a value set for that
2034+
// column, then we can completely omit inserting it.
2035+
bool skipSinglePKField = false;
2036+
2037+
if ( ( mPrimaryKeyType == PktInt || mPrimaryKeyType == PktFidMap || mPrimaryKeyType == PktUint64 ) )
20332038
{
2034-
Q_FOREACH ( int idx, mPrimaryKeyAttrs )
2039+
if ( mPrimaryKeyAttrs.size() == 1 &&
2040+
defaultValueClause( mPrimaryKeyAttrs[0] ).startsWith( "nextval(" ) )
20352041
{
2036-
insert += delim + quotedIdentifier( field( idx ).name() );
2037-
values += delim + QStringLiteral( "$%1" ).arg( defaultValues.size() + offset );
2038-
delim = ',';
2039-
fieldId << idx;
2040-
defaultValues << defaultValueClause( idx );
2042+
bool foundNonNullPK = false;
2043+
int idx = mPrimaryKeyAttrs[0];
2044+
for ( int i = 0; i < flist.size(); i++ )
2045+
{
2046+
QgsAttributes attrs2 = flist[i].attributes();
2047+
QVariant v2 = attrs2.value( idx, QVariant( QVariant::Int ) );
2048+
if ( !v2.isNull() )
2049+
{
2050+
foundNonNullPK = true;
2051+
break;
2052+
}
2053+
}
2054+
skipSinglePKField = !foundNonNullPK;
2055+
}
2056+
2057+
if ( !skipSinglePKField )
2058+
{
2059+
Q_FOREACH ( int idx, mPrimaryKeyAttrs )
2060+
{
2061+
insert += delim + quotedIdentifier( field( idx ).name() );
2062+
values += delim + QStringLiteral( "$%1" ).arg( defaultValues.size() + offset );
2063+
delim = ',';
2064+
fieldId << idx;
2065+
defaultValues << defaultValueClause( idx );
2066+
}
20412067
}
20422068
}
20432069

@@ -2048,6 +2074,8 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist, Flags flags )
20482074
for ( int idx = 0; idx < attributevec.count(); ++idx )
20492075
{
20502076
QVariant v = attributevec.value( idx, QVariant( QVariant::Int ) ); // default to NULL for missing attributes
2077+
if ( skipSinglePKField && idx == mPrimaryKeyAttrs[0] )
2078+
continue;
20512079
if ( fieldId.contains( idx ) )
20522080
continue;
20532081

0 commit comments

Comments
 (0)
Please sign in to comment.