Describe the bug
isExistsTable() asks the catalog for every table of the database and looks for a match in Java — no catalog filter, no schema filter, no table name:
// opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/JDBCStorage.java:269
try (final ResultSet rs = con.getMetaData().getTables(null, null, null, new String[]{"TABLE"})) {
while (rs.next()) {
if (tree2table.get(treeName).equalsIgnoreCase(rs.getString("TABLE_NAME"))) {
It is called from openTree(createOnDemand) — through AbstractTree.open(), which every tree of the backend goes through — and from deleteTree(). So opening a backend walks the whole catalog once per tree: about 25 times for a stock suffix, and the cost is O(trees × tables in the database) for what ought to be a single indexed lookup. A JDBC backend sharing its database with another application pays for that application's tables too, on every open.
The same two DatabaseMetaData calls of this class — getTables() here and getIndexInfo() in isExistsIndex() — also take no setQueryTimeout, so they are outside the statement bounds of #877/#882 and can only be bounded by the read timeout asked for in #885. Making this one cheap is the fix that matters; the bound is the smaller half.
Impact
The open of a backend, and dsconfig create-backend-index on a running server, are slower than they need to be by a factor that grows with what else lives in the database — a cost that is invisible in a test database and grows quietly in a shared production one.
Expected behavior
- the table name is passed to
getTables() as the pattern, so the driver asks its catalog for one row rather than all of them;
- the name is passed in the form the catalog stores it — an unquoted identifier is folded to upper case on Oracle and to lower case on PostgreSQL, and a metadata pattern is matched against the stored form — asked of the driver through
storesUpperCaseIdentifiers() / storesLowerCaseIdentifiers() rather than by matching its class name, as the dialect switches elsewhere in this class do;
- the name of the row that comes back is still compared, since
_ is a single-character wildcard in a metadata pattern.
Environment
master (5.2.x), all four JDBC dialects (PostgreSQL, MySQL, Oracle, MS SQL Server).
Split out of #885, which keeps the two bounds that live in CachedConnection.
Describe the bug
isExistsTable()asks the catalog for every table of the database and looks for a match in Java — no catalog filter, no schema filter, no table name:It is called from
openTree(createOnDemand)— throughAbstractTree.open(), which every tree of the backend goes through — and fromdeleteTree(). So opening a backend walks the whole catalog once per tree: about 25 times for a stock suffix, and the cost is O(trees × tables in the database) for what ought to be a single indexed lookup. A JDBC backend sharing its database with another application pays for that application's tables too, on every open.The same two
DatabaseMetaDatacalls of this class —getTables()here andgetIndexInfo()inisExistsIndex()— also take nosetQueryTimeout, so they are outside the statement bounds of #877/#882 and can only be bounded by the read timeout asked for in #885. Making this one cheap is the fix that matters; the bound is the smaller half.Impact
The open of a backend, and
dsconfig create-backend-indexon a running server, are slower than they need to be by a factor that grows with what else lives in the database — a cost that is invisible in a test database and grows quietly in a shared production one.Expected behavior
getTables()as the pattern, so the driver asks its catalog for one row rather than all of them;storesUpperCaseIdentifiers()/storesLowerCaseIdentifiers()rather than by matching its class name, as the dialect switches elsewhere in this class do;_is a single-character wildcard in a metadata pattern.Environment
master (5.2.x), all four JDBC dialects (PostgreSQL, MySQL, Oracle, MS SQL Server).
Split out of #885, which keeps the two bounds that live in
CachedConnection.