Skip to content

Commit 81af573

Browse files
committed
perf(model-server): inefficient SQL query was generated for getAll
After adding the repository column to the primary key, a different SQL query was generated that is less efficient. Adjusted the PostgresDialect to generate a query with comparable performance to the one for single column primary keys.
1 parent 7f9e1e6 commit 81af573

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

model-server/src/main/kotlin/org/modelix/model/server/store/PostgresDialect.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,47 @@ class PostgresDialect : BasicJdbcDialect() {
5353
updPart,
5454
)
5555
}
56+
57+
override fun loadQuery(
58+
fullTblName: String,
59+
keyCols: Collection<String>,
60+
cols: Iterable<String>,
61+
keyCnt: Int,
62+
): String {
63+
assert(!keyCols.isEmpty())
64+
if (keyCols.size == 1 || keyCnt == 1) return super.loadQuery(fullTblName, keyCols, cols, keyCnt)
65+
66+
/*
67+
The default implementation generates a query that looks like this:
68+
69+
SELECT "repository","key","value"
70+
FROM "modelix"."model"
71+
WHERE
72+
(repository=? AND key=?) OR
73+
(repository=? AND key=?)
74+
75+
Postgres creates a query plan that still uses the index, but is not optimal.
76+
77+
For single column primary keys a query using the IN operator would be generated and that leads to a more
78+
efficient query plan.
79+
80+
For the following query a plan is created that is comparable in performance to the IN operator.
81+
82+
SELECT repository, key, value
83+
FROM modelix.model
84+
JOIN (
85+
VALUES
86+
(?, ?),
87+
(?, ?)
88+
) as t (k0,k1)
89+
ON k0 = repository AND k1 = key
90+
*/
91+
92+
val valuesList = (1..keyCnt).joinToString(", ") { "(?, ?)" }
93+
val subSelectColumns = keyCols.withIndex().joinToString(",") { "k${it.index}" }
94+
val joinCondition = keyCols.withIndex().joinToString(" AND ") { "k${it.index} = ${it.value}" }
95+
val joinPart = """JOIN (VALUES $valuesList) as t ($subSelectColumns) ON $joinCondition"""
96+
val result = """SELECT ${cols.joinToString(", ")} FROM $fullTblName $joinPart"""
97+
return result
98+
}
5699
}

0 commit comments

Comments
 (0)