[#3560] Slow discovery of primary keys in very large MySQL databases

This commit is contained in:
Lukas Eder 2014-08-15 13:56:04 +02:00
parent 8dbff7fc0b
commit 57650f08e3
12 changed files with 179 additions and 47 deletions

View File

@ -41,12 +41,13 @@
package org.jooq.util.mysql;
import static org.jooq.impl.DSL.inline;
import static org.jooq.util.mysql.information_schema.Tables.COLUMNS;
import static org.jooq.util.mysql.information_schema.Tables.KEY_COLUMN_USAGE;
import static org.jooq.util.mysql.information_schema.Tables.REFERENTIAL_CONSTRAINTS;
import static org.jooq.util.mysql.information_schema.Tables.SCHEMATA;
import static org.jooq.util.mysql.information_schema.Tables.STATISTICS;
import static org.jooq.util.mysql.information_schema.Tables.TABLES;
import static org.jooq.util.mysql.information_schema.Tables.TABLE_CONSTRAINTS;
import static org.jooq.util.mysql.mysql.tables.Proc.DB;
import static org.jooq.util.mysql.mysql.tables.Proc.PROC;
@ -85,7 +86,7 @@ import org.jooq.util.mysql.information_schema.tables.Columns;
import org.jooq.util.mysql.information_schema.tables.KeyColumnUsage;
import org.jooq.util.mysql.information_schema.tables.ReferentialConstraints;
import org.jooq.util.mysql.information_schema.tables.Schemata;
import org.jooq.util.mysql.information_schema.tables.TableConstraints;
import org.jooq.util.mysql.information_schema.tables.Statistics;
import org.jooq.util.mysql.information_schema.tables.Tables;
import org.jooq.util.mysql.mysql.enums.ProcType;
import org.jooq.util.mysql.mysql.tables.Proc;
@ -99,11 +100,11 @@ public class MySQLDatabase extends AbstractDatabase {
@Override
protected void loadPrimaryKeys(DefaultRelations relations) throws SQLException {
for (Record record : fetchKeys("PRIMARY KEY")) {
SchemaDefinition schema = getSchema(record.getValue(KeyColumnUsage.TABLE_SCHEMA));
String constraintName = record.getValue(KeyColumnUsage.CONSTRAINT_NAME);
String tableName = record.getValue(KeyColumnUsage.TABLE_NAME);
String columnName = record.getValue(KeyColumnUsage.COLUMN_NAME);
for (Record record : fetchKeys(true)) {
SchemaDefinition schema = getSchema(record.getValue(Statistics.TABLE_SCHEMA));
String constraintName = record.getValue(Statistics.INDEX_NAME);
String tableName = record.getValue(Statistics.TABLE_NAME);
String columnName = record.getValue(Statistics.COLUMN_NAME);
String key = getKeyName(tableName, constraintName);
TableDefinition table = getTable(schema, tableName);
@ -116,11 +117,11 @@ public class MySQLDatabase extends AbstractDatabase {
@Override
protected void loadUniqueKeys(DefaultRelations relations) throws SQLException {
for (Record record : fetchKeys("UNIQUE")) {
SchemaDefinition schema = getSchema(record.getValue(KeyColumnUsage.TABLE_SCHEMA));
String constraintName = record.getValue(KeyColumnUsage.CONSTRAINT_NAME);
String tableName = record.getValue(KeyColumnUsage.TABLE_NAME);
String columnName = record.getValue(KeyColumnUsage.COLUMN_NAME);
for (Record record : fetchKeys(false)) {
SchemaDefinition schema = getSchema(record.getValue(Statistics.TABLE_SCHEMA));
String constraintName = record.getValue(Statistics.INDEX_NAME);
String tableName = record.getValue(Statistics.TABLE_NAME);
String columnName = record.getValue(Statistics.COLUMN_NAME);
String key = getKeyName(tableName, constraintName);
TableDefinition table = getTable(schema, tableName);
@ -135,24 +136,26 @@ public class MySQLDatabase extends AbstractDatabase {
return "KEY_" + tableName + "_" + keyName;
}
private Result<Record4<String, String, String, String>> fetchKeys(String constraintType) {
private Result<Record4<String, String, String, String>> fetchKeys(boolean primary) {
// [#3560] It has been shown that querying the STATISTICS table is much faster on
// very large databases than going through TABLE_CONSTRAINTS and KEY_COLUMN_USAGE
return create().select(
KeyColumnUsage.TABLE_SCHEMA,
KeyColumnUsage.CONSTRAINT_NAME,
KeyColumnUsage.TABLE_NAME,
KeyColumnUsage.COLUMN_NAME)
.from(KEY_COLUMN_USAGE)
.join(TABLE_CONSTRAINTS)
.on(KeyColumnUsage.TABLE_SCHEMA.equal(TableConstraints.TABLE_SCHEMA))
.and(KeyColumnUsage.TABLE_NAME.equal(TableConstraints.TABLE_NAME))
.and(KeyColumnUsage.CONSTRAINT_NAME.equal(TableConstraints.CONSTRAINT_NAME))
.where(TableConstraints.CONSTRAINT_TYPE.equal(constraintType))
.and(KeyColumnUsage.TABLE_SCHEMA.in(getInputSchemata()))
.orderBy(
KeyColumnUsage.TABLE_SCHEMA.asc(),
KeyColumnUsage.TABLE_NAME.asc(),
KeyColumnUsage.ORDINAL_POSITION.asc())
.fetch();
Statistics.TABLE_SCHEMA,
Statistics.TABLE_NAME,
Statistics.COLUMN_NAME,
Statistics.INDEX_NAME)
.from(STATISTICS)
.where(Statistics.TABLE_SCHEMA.in(getInputSchemata()))
.and(primary
? Statistics.INDEX_NAME.eq(inline("PRIMARY"))
: Statistics.INDEX_NAME.ne(inline("PRIMARY")).and(Statistics.NON_UNIQUE.eq(inline(0L))))
.orderBy(
Statistics.TABLE_SCHEMA,
Statistics.TABLE_NAME,
Statistics.INDEX_NAME,
Statistics.SEQ_IN_INDEX)
.fetch();
}
@Override

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class InformationSchema extends org.jooq.impl.SchemaImpl {
private static final long serialVersionUID = -611052785;
private static final long serialVersionUID = -679998315;
/**
* The singleton instance of <code>information_schema</code>
@ -39,6 +39,7 @@ public class InformationSchema extends org.jooq.impl.SchemaImpl {
org.jooq.util.mysql.information_schema.tables.Parameters.PARAMETERS,
org.jooq.util.mysql.information_schema.tables.ReferentialConstraints.REFERENTIAL_CONSTRAINTS,
org.jooq.util.mysql.information_schema.tables.Schemata.SCHEMATA,
org.jooq.util.mysql.information_schema.tables.Statistics.STATISTICS,
org.jooq.util.mysql.information_schema.tables.Tables.TABLES,
org.jooq.util.mysql.information_schema.tables.TableConstraints.TABLE_CONSTRAINTS);
}

View File

@ -8,7 +8,7 @@ package org.jooq.util.mysql.information_schema;
*
* Convenience access to all tables in information_schema
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Tables {
@ -38,6 +38,11 @@ public class Tables {
*/
public static final org.jooq.util.mysql.information_schema.tables.Schemata SCHEMATA = org.jooq.util.mysql.information_schema.tables.Schemata.SCHEMATA;
/**
* The table information_schema.STATISTICS
*/
public static final org.jooq.util.mysql.information_schema.tables.Statistics STATISTICS = org.jooq.util.mysql.information_schema.tables.Statistics.STATISTICS;
/**
* The table information_schema.TABLES
*/

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Columns extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = -840872510;
private static final long serialVersionUID = -1192516157;
/**
* The singleton instance of <code>information_schema.COLUMNS</code>

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class KeyColumnUsage extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = -1303145965;
private static final long serialVersionUID = -669574892;
/**
* The singleton instance of <code>information_schema.KEY_COLUMN_USAGE</code>

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Parameters extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = -564000748;
private static final long serialVersionUID = 1665633877;
/**
* The singleton instance of <code>information_schema.PARAMETERS</code>

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class ReferentialConstraints extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = -514911080;
private static final long serialVersionUID = 1234359031;
/**
* The singleton instance of <code>information_schema.REFERENTIAL_CONSTRAINTS</code>

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Schemata extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = 1266409808;
private static final long serialVersionUID = -2145867409;
/**
* The singleton instance of <code>information_schema.SCHEMATA</code>

View File

@ -0,0 +1,123 @@
/**
* This class is generated by jOOQ
*/
package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Statistics extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = 357430055;
/**
* The singleton instance of <code>information_schema.STATISTICS</code>
*/
public static final org.jooq.util.mysql.information_schema.tables.Statistics STATISTICS = new org.jooq.util.mysql.information_schema.tables.Statistics();
/**
* The class holding records for this type
*/
@Override
public java.lang.Class<org.jooq.Record> getRecordType() {
return org.jooq.Record.class;
}
/**
* The column <code>information_schema.STATISTICS.TABLE_CATALOG</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> TABLE_CATALOG = createField("TABLE_CATALOG", org.jooq.impl.SQLDataType.VARCHAR.length(512).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.TABLE_SCHEMA</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> TABLE_SCHEMA = createField("TABLE_SCHEMA", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.TABLE_NAME</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> TABLE_NAME = createField("TABLE_NAME", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.NON_UNIQUE</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> NON_UNIQUE = createField("NON_UNIQUE", org.jooq.impl.SQLDataType.BIGINT.nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.INDEX_SCHEMA</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_SCHEMA = createField("INDEX_SCHEMA", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.INDEX_NAME</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_NAME = createField("INDEX_NAME", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.SEQ_IN_INDEX</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> SEQ_IN_INDEX = createField("SEQ_IN_INDEX", org.jooq.impl.SQLDataType.BIGINT.nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.COLUMN_NAME</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> COLUMN_NAME = createField("COLUMN_NAME", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.COLLATION</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> COLLATION = createField("COLLATION", org.jooq.impl.SQLDataType.VARCHAR.length(1), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.CARDINALITY</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> CARDINALITY = createField("CARDINALITY", org.jooq.impl.SQLDataType.BIGINT, STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.SUB_PART</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> SUB_PART = createField("SUB_PART", org.jooq.impl.SQLDataType.BIGINT, STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.PACKED</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> PACKED = createField("PACKED", org.jooq.impl.SQLDataType.VARCHAR.length(10), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.NULLABLE</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> NULLABLE = createField("NULLABLE", org.jooq.impl.SQLDataType.VARCHAR.length(3).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.INDEX_TYPE</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_TYPE = createField("INDEX_TYPE", org.jooq.impl.SQLDataType.VARCHAR.length(16).nullable(false).defaulted(true), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.COMMENT</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> COMMENT = createField("COMMENT", org.jooq.impl.SQLDataType.VARCHAR.length(16), STATISTICS, "");
/**
* The column <code>information_schema.STATISTICS.INDEX_COMMENT</code>.
*/
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_COMMENT = createField("INDEX_COMMENT", org.jooq.impl.SQLDataType.VARCHAR.length(1024).nullable(false).defaulted(true), STATISTICS, "");
/**
* No further instances allowed
*/
private Statistics() {
this("STATISTICS", null);
}
private Statistics(java.lang.String alias, org.jooq.Table<org.jooq.Record> aliased) {
this(alias, aliased, null);
}
private Statistics(java.lang.String alias, org.jooq.Table<org.jooq.Record> aliased, org.jooq.Field<?>[] parameters) {
super(alias, org.jooq.util.mysql.information_schema.InformationSchema.INFORMATION_SCHEMA, aliased, parameters, "");
}
}

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class TableConstraints extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = 2008733278;
private static final long serialVersionUID = -1909788577;
/**
* The singleton instance of <code>information_schema.TABLE_CONSTRAINTS</code>

View File

@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Tables extends org.jooq.impl.TableImpl<org.jooq.Record> {
private static final long serialVersionUID = 1927949993;
private static final long serialVersionUID = 1728740650;
/**
* The singleton instance of <code>information_schema.TABLES</code>

View File

@ -2468,7 +2468,7 @@
<name>org.jooq.util.DefaultGenerator</name>
<database>
<name>org.jooq.util.mysql.MySQLDatabase</name>
<includes>COLUMNS|KEY_COLUMN_USAGE|PARAMETERS|REFERENTIAL_CONSTRAINTS|SCHEMATA|TABLE_CONSTRAINTS|TABLES</includes>
<includes>COLUMNS|KEY_COLUMN_USAGE|PARAMETERS|REFERENTIAL_CONSTRAINTS|SCHEMATA|STATISTICS|TABLE_CONSTRAINTS|TABLES</includes>
<excludes></excludes>
<recordVersionFields></recordVersionFields>
<recordTimestampFields></recordTimestampFields>