It hurts if server has millions of tables.

See https://github.com/ClickHouse/ClickHouse/pull/3398
Please add some tests to ensure it won't be broken in future.
if (!create_query.is_dictionary)
            pool.scheduleOrThrowOnError([&]()
            {
                tryAttachTable(
                    context,
                    create_query,
                    *this,
                    getDatabaseName(),
                    getMetadataPath() + name_with_query.first,
                    has_force_restore_data_flag);
                
                logAboutProgress(log, ++tables_processed, total_tables, watch);
            });
    }
    pool.wait();
    
    startupTables(pool);
    
    for (const auto & [name, query] : file_names)
    {
        auto create_query = query->as<const ASTCreateQuery &>();
        if (create_query.is_dictionary)
        {
            tryAttachDictionary(query, *this, getMetadataPath() + name);
            
            logAboutProgress(log, ++dictionaries_processed, total_dictionaries, watch);
        }
    }
}
void DatabaseOrdinary::startupTables(ThreadPool & thread_pool)