 This bug is reproduced on any version ( 22.1.3.7 , 22.3.11.12 , 22.9.3)

**How to reproduce** 
*(cant reproduce well on fiddle, but easy locally or on production)*

**NOT OK (with preallocate)**
```
CREATE TABLE default.oom_table (key String) ENGINE = MergeTree() ORDER BY tuple();

INSERT INTO default.oom_table SELECT hex(sipHash128(toString(number % 100))) FROM numbers(1000000000);

CREATE VIEW default.oom_view AS SELECT xxHash32(key) hash, key FROM default.oom_table GROUP BY key;

CREATE DICTIONARY default.oom_dict (hash UInt32, key String) PRIMARY KEY hash SOURCE(CLICKHOUSE(host 'localhost' user 'default' port 9000 db 'default' table 'oom_view')) LAYOUT (HASHED(PREALLOCATE 1)) LIFETIME (600);

SELECT * FROM dictionary('default.oom_dict');
```

**Error**
```
Code: 241. DB::Exception: Received from clickhouse-server:9000. DB::Exception: Memory limit (total) exceeded: would use 48.48 GiB (attempt to allocate chunk of 51540792506 bytes), maximum: 13.50 GiB. OvercommitTracker decision: Query was selected to stop by OvercommitTracker.. (MEMORY_LIMIT_EXCEEDED)

```

**OK (without preallocate)**
```
CREATE TABLE default.oom_table (key String) ENGINE = MergeTree() ORDER BY tuple();

INSERT INTO default.oom_table SELECT hex(sipHash128(toString(number % 100))) FROM numbers(1000000000);

CREATE VIEW default.oom_view AS SELECT xxHash32(key) hash, key FROM default.oom_table GROUP BY key;

CREATE DICTIONARY default.oom_dict (hash UInt32, key String) PRIMARY KEY hash SOURCE(CLICKHOUSE(host 'localhost' user 'default' port 9000 db 'default' table 'oom_view')) LAYOUT (HASHED()) LIFETIME (600);

SELECT * FROM dictionary('default.oom_dict');
```


* NOTE: result_size_hint may be changed during you are reading (usually it
     * will be non zero for the first block and zero for others, since it uses
     * Progress::total_rows_approx,) from the pipe, and may be called
     * in parallel, so you should use something like this:
     *
     *   ...
     *   std::atomic<uint64_t> new_size = 0;
     *
     *   QueryPipeline pipeline;
     *   pipeline.init(source->loadAll(&new_size));
     *   PullingPipelineExecutor executor;
     *
     *   Block block;
     *   while (executor.pull(block))
     *   {
     *       if (new_size)
     *       {
     *           size_t current_new_size = new_size.exchange(0);
     *           if (current_new_size)
     *               resize(current_new_size);
     *       }
     *       else
     *       {
     *           resize(block.rows());
     *       }
     *   }
     *
     *   ...
     */
    virtual QueryPipeline loadAllWithSizeHint(std::atomic<size_t> * )