Batasan partisi tidak digunakan untuk bergabung yang melibatkan tabel dipartisi oleh timestamp

11

Saya memiliki struktur tabel dipartisi seperti:

CREATE TABLE measurements (
    sensor_id bigint,
    tx timestamp,
    measurement int
);

CREATE TABLE measurements_201201(
    CHECK (tx >= '2012-01-01 00:00:00'::timestamp without time zone 
       AND tx < ('2012-01-01 00:00:00'::timestamp without time zone + '1 mon'::interval))    
)INHERITS (measurements);
CREATE INDEX ON measurements_201201(sensor_id);
CREATE INDEX ON measurements_201201(tx);
CREATE INDEX ON measurements_201201(sensor_id, tx);
....

Dan seterusnya. Setiap tabel memiliki sekitar 20 juta baris.

Jika saya meminta sampel sensor dan sampel cap waktu dalam WHEREklausa, rencana kueri menunjukkan tabel yang benar yang dipilih dan indeks yang digunakanm misalnya:

SELECT *
FROM measurements
INNER JOIN sensors TABLESAMPLE BERNOULLI (0.01) USING (sensor_id)
WHERE tx BETWEEN '2015-01-04 05:00' AND '2015-01-04 06:00' 
    OR tx BETWEEN '2015-02-04 05:00' AND '2015-02-04 06:00' 
    OR tx BETWEEN '2014-03-05 05:00' AND '2014-04-07 06:00' ;

Namun, jika saya menggunakan CTE, atau memasukkan nilai cap waktu ke dalam tabel (tidak ditampilkan, bahkan dengan indeks pada tabel sementara).

WITH sensor_sample AS(
    SELECT sensor_id, start_ts, end_ts
    FROM sensors TABLESAMPLE BERNOULLI (0.01)
    CROSS JOIN (VALUES (TIMESTAMP '2015-01-04 05:00', TIMESTAMP '2015-01-04 06:00'),
        (TIMESTAMP '2015-02-04 05:00', TIMESTAMP '2015-02-04 06:00'),
        (TIMESTAMP  '2014-03-05 05:00', '2014-04-07 06:00') ) tstamps(start_ts, end_ts)
)

Sesuatu seperti di bawah ini

SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts

Melakukan pemindaian indeks pada setiap tabel. Yang masih relatif cepat, tetapi dengan meningkatnya kompleksitas kueri, ini dapat berubah menjadi pemindaian seq yang akan berakhir sangat lambat untuk mengambil ~ 40K baris dari subset terbatas dari tabel partisi (4-5 dari 50).

Saya khawatir sesuatu seperti ini adalah masalahnya.

Untuk ekspresi non-sepele Anda harus mengulangi kondisi kata demi kata dalam atau kurang lebih untuk membuat perencana kueri Postgres memahaminya dapat mengandalkan kendala PERIKSA. Bahkan jika itu tampak berlebihan!

Bagaimana saya bisa meningkatkan struktur partisi dan permintaan untuk mengurangi kemungkinan menjalankan pemindaian seq pada semua data saya?

raphael
sumber
1
pertanyaan besar - tetapi akan lebih baik lagi jika Anda menempelkan hasil EXPLAIN (ANALYZE, BUFFERS)
filiprem

Jawaban:

1

Pengecualian berbasis kendala [CBE] dilakukan pada tahap awal perencanaan kueri, tepat setelah kueri diuraikan, dipetakan ke hubungan aktual, dan ditulis ulang. ( internal , tahap Perencana / Pengoptimal)

Perencana tidak dapat mengambil konten tabel "sensor_sample".

Jadi kecuali Anda memiliki nilai yang di-hardcode dalam kueri, perencana tidak akan mengecualikan "partisi".

Saya kira apa yang terjadi dengan varian CTE ... perencana dibatasi karena Anda menggunakan TABLESAMPLE dan seluruh subquery dapat diperlakukan sebagai volatile bahkan jika literal dalam subquery itu statis. ( Itu hanya dugaan saya, saya bukan ahli kode perencana )

Sisi baiknya, pemindaian indeks dengan hasil negatif sangat cepat. (pemindaian satu halaman paling banyak!) jadi kecuali Anda memiliki lebih dari 10.000 partisi, saya tidak akan repot.

Jadi, untuk menjawab pertanyaan Anda secara langsung:

  • Anda tidak dapat meningkatkan struktur data ini lebih jauh.

  • Scan indeks Regardin - harganya murah;

  • Mengenai pemindaian berurutan - mereka dihindari jika memungkinkan, seperti yang Anda lihat pada contoh Anda sendiri.

filiprem
sumber