Liquibase tableExists не масштабируется - PullRequest
0 голосов
/ 23 января 2019

Я запускаю ChangeSet, который должен проверить, существует ли таблица в предварительном условии. Так что мой набор изменений выглядит как

<changeSet author="James" id="1548255530845-100">
    <preConditions onFail="MARK_RAN">
            <not>
                    <tableExists tableName="MY_NEW_TABLE" schemaName="${my_schema}"></tableExists>
            </not>
    </preConditions>
    <createTable tableName="MY_NEW_TABLE">
        <column name="IDX" type="${integer.type}">
            <constraints nullable="false"/>
        </column>
        <column name="INTVAL" type="${integer.type}"/>
    </createTable>
</changeSet>

Когда я запускаю это в большой базе данных / схеме, это занимает очень много времени для запуска.

Отладка кода, вызываемого внутренними компонентами Liquibase, - SnapshotGeneratorFactory.has (DatabaseObject, Database)

public boolean has(DatabaseObject example, Database database) throws DatabaseException, InvalidExampleException {
    List<Class<? extends DatabaseObject>> types = new ArrayList<Class<? extends DatabaseObject>>(getContainerTypes(example.getClass(), database));
    types.add(example.getClass());

    //workaround for common check for databasechangelog/lock table to not snapshot the whole database like we have to in order to handle case issues
    if (example instanceof Table && (example.getName().equals(database.getDatabaseChangeLogTableName()) || example.getName().equals(database.getDatabaseChangeLogLockTableName()))) {
        try {
            ExecutorService.getInstance().getExecutor(database).queryForInt(new RawSqlStatement("select count(*) from " + database.escapeObjectName(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), example.getName(), Table.class)));
            return true;
        } catch (DatabaseException e) {
            if (database instanceof PostgresDatabase) { //throws "current transaction is aborted" unless we roll back the connection
                database.rollback();
            }
            return false;
        }
    }

    if (createSnapshot(example, database, new SnapshotControl(database, false, types.toArray(new Class[types.size()]))) != null) {
        return true;
    }
    CatalogAndSchema catalogAndSchema;
    if (example.getSchema() == null) {
        catalogAndSchema = database.getDefaultSchema();
    } else {
        catalogAndSchema = example.getSchema().toCatalogAndSchema();
    }
    DatabaseSnapshot snapshot = createSnapshot(catalogAndSchema, database, new SnapshotControl(database, false, example.getClass()));
    for (DatabaseObject obj : snapshot.get(example.getClass())) {
        if (DatabaseObjectComparatorFactory.getInstance().isSameObject(example, obj, null, database)) {
            return true;
        }
    }
    return false;
}

Затем код создает снимок базы данных и просматривает каждую таблицу, чтобы проверить, является ли она «isSameObject»

Это просто не масштабируется, чем больше таблиц у меня в базе данных, тем больше времени потребуется, чтобы проверить, существует ли таблица.

Я заметил, что в методе выше есть комментарий для «обходного пути», поэтому при поиске в таблице exchangeloglog / lock не требуется выполнять такой снимок, а затем масштабируемый поиск.

Существует ли масштабируемый способ проверить, существует ли таблица / не существует в предварительном условии?

Еще одна небольшая проблема с методом: типы List в начале метода содержат дважды «class liquibase.structure.core.Table», когда я проверяю, существуют ли таблицы. Разве это не должно быть множеством, поэтому избегайте дубликатов? И разве он не должен быть заполнен только после того, как "рабочая среда" была выполнена?

...