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 (processed % PRINT_MESSAGE_EACH_N_OBJECTS == 0 || watch.compareAndRestart(PRINT_MESSAGE_EACH_N_SECONDS))
        {
            LOG_INFO(log, "{}%", processed * 100.0 / total);
            watch.restart();
        }
    }
}
DatabaseOrdinary::DatabaseOrdinary(const String & name_, const String & metadata_path_, const Context & context_)
    : DatabaseOrdinary(name_, metadata_path_, "data/" + escapeForFileName(name_) + "/", "DatabaseOrdinary (" + name_ + ")", context_)
{
}
DatabaseOrdinary::DatabaseOrdinary(
    const String & name_, const String & metadata_path_, const String & data_path_, const String & logger, const Context & context_)
    : DatabaseWithDictionaries(name_, metadata_path_, data_path_, logger, context_)
{
}
void DatabaseOrdinary::loadStoredObjects(Context & context, bool has_force_restore_data_flag)
{
    /** Tables load faster if they are loaded in sorted (by name) order.
      * Otherwise (for the ext4 filesystem), `DirectoryIterator` iterates through them in some order,
      *  which does not correspond to order tables creation and does not correspond to order of their location on disk.
      */
    using FileNames = std::map<std::string, ASTPtr>;
    FileNames file_names;
    size_t total_dictionaries = 0;
    auto process_metadata = [&context, &file_names, &total_dictionaries, this](const String & file_name)
    {