**Describe the situation**

```
SELECT * FROM test.hits INTO OUTFILE 'dump.csv' FORMAT CSV

8873898 rows in set. Elapsed: 32.487 sec. Processed 8.87 million rows, 8.46 GB (273.15 thousand rows/s., 260.42 MB/s.)
```

is bounded by single CPU core. Too slow :(
if (have_error && report_error)
        processError(full_query
}
MultiQueryProcessingStage ClientBase::analyzeMultiQueryText(
    const char *& this_query_begin, const char *& th const char * all_queries_end,
    String & query_to_execute, ASTPtr & parsed_query, const String & all_queries_text,
    std::optional<Exception> & current_exception)
{
    if (this_query_begin >= all_queries_end)
        return MultiQueryProcessingStage::QUERIES_END;
    // Remove leading empty newlines and other whitespace, because they
    // are annoying to filter in query log. This is mostly relevant for
    // the tests.
    while (this_query_ueries_end && isWhitespaceASCII(*this_query_begin))
        ++this_query_begin;
    if (this_query_begin >= all_queries_end)
        return MultiQueryProcessingStage::QUERIES_END;
    // If there are only comments left until the end of file, we just
    // stop. The parser can't handle this situation because it always
    // expects that there is some query that it can parse.
    // We can get into this situation because the parser also doesn't
    // skip the trailing comments after parsing a query. This is because
    // they may as well be the leading comments for the next query,
    // and it makes more sense to treat them as such.
    {
        Tokens tokens(this_query_begin, all_queries_end
        IParser::Pos token_iterator(tokens, global_context->getSettingsRef().max_parser_depth
        if (!token_iterator.isValid())
            return MultiQueryProcessingStage::QUERIES_END;
    }