我正在运行一个 ChangeSet,需要检查前提条件中是否存在表。所以我的 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>
Run Code Online (Sandbox Code Playgroud)
当我在大型数据库/模式上运行它时,它需要很长时间才能运行。
调试 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;
}
Run Code Online (Sandbox Code Playgroud)
然后,代码创建数据库的快照并循环遍历每个表以检查它是否“isSameObject”
这只是无法扩展,数据库中的表越多,检查表是否存在所需的时间就越长。
我注意到上面的方法中有一个注释用于“解决方法”,因此查找数据库更改日志/锁定表不必执行这种快照,然后执行不可扩展的查找。
是否有一种可扩展的方法来检查前提条件中表是否存在/不存在?
该方法的另一个小问题:当我检查表是否存在时,该方法开头的列表类型包含“class liquibase.struct.core.Table”两次。这不应该是一个 Set - 所以避免重复吗?难道不应该只在执行“解决方法”后才填充它吗?
| 归档时间: |
|
| 查看次数: |
2260 次 |
| 最近记录: |