apache / apache/arrow

[Python] pyarrow.Table.take() is much slower when reading a parquet with read_table instead of from_batches since pyarrow 8.0.0

Open
#44,317 3 comments 0 reactions 1 assignee Claimed by @anjakefala View on GitHub
Component: Python Type: bug
Dominant language
C++
Stars
17.1k
Forks
4.3k
Avg merge
3d 13h
Merged PRs (30d)
88

Description

### Describe the bug, including details regarding any error messages, version, and platform.

After upgrading pyarrow 7.0.0 to pyarrow 17.0.0 I noticed a major performance slowdown (200 times slower) on a `pyarrow.Table.take()` operation performed on a Table loaded from a parquet file.

The issue seems to be in `pq.read_table`, which became a lot slower in pyarrow >7.0.0. The same issue is not there if the parquet is read with pa.Table.from_batches.

Minimal code to reproduce the issue:

import timeit

import numpy as np
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq

parquet_path = "parquet_test.parquet"
n_cols = 20
n_rows = 10**6
df = pd.DataFrame({f"{col}": np.random.random(n_rows) for col in range(n_cols)})
df.to_parquet(parquet_path)

table = pq.read_table(parquet_path)
# table = pa.Table.from_batches(list(pq.ParquetFile(parquet_path).iter_batches(batch_size=10**9)))

def profile_take():
table.take([2])

samples = 100
execution_time = timeit.timeit(profile_take, number=samples)

print(f"Table shape {table.shape}. Average time taken for take() call: {execution_time / samples:.5f} seconds")

Output of the script above with `read_table`:
1. Pyarrow 7.0.0 -> Table shape (1000000, 20). Average time taken for take() call: 0.00021 seconds
2. Pyarrow 8.0.0 -> Table shape (1000000, 20). Average time taken for take() call: **0.03463** seconds (**165x slower than pyarrow 7.0.0**)
3. Pyarrow 17.0.0 -> Table shape (1000000, 20). Average time taken for take() call: **0.11914** seconds (**567x slower than pyarrow 7.0.0**)

Output of the script above with `from_batches` and `batch_size=10**9` (in this case there is no major difference):
1. Pyarrow 7.0.0 -> Table shape (1000000, 20). Average time taken for take() call: 0.00010 seconds
2. Pyarrow 8.0.0 -> Table shape (1000000, 20). Average time taken for take() call: 0.00013 seconds
3. Pyarrow 17.0.0 -> Table shape (1000000, 20). Average time taken for take() call: 0.00009 seconds

However if using `batch_size=10**5` in `iter_batches` the total time is approx *0.10451 seconds*, so there is a slowdown similar to the one of `read_table`.

There seems to be some other `read_table` issues which might be related (in particular the first):
https://github.com/apache/arrow/issues/32108
https://github.com/apache/arrow/issues/23368
https://github.com/apache/arrow/issues/38389
https://github.com/apache/arrow/issues/13720
https://github.com/apache/arrow/issues/37666

### Component(s)

Python

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.