PostgreSQL Common Table Expressions vs tabel sementara?

11

The PostgreSQL dokumentasi di DENGAN menunjukkan contoh berikut:

WITH regional_sales AS (
        SELECT region, SUM(amount) AS total_sales
        FROM orders
        GROUP BY region
     ), top_regions AS (
        SELECT region
        FROM regional_sales
        WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
     )
SELECT region,
       product,
       SUM(quantity) AS product_units,
       SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

Itu juga mencatat:

Properti yang berguna dari kueri WITH adalah bahwa mereka dievaluasi hanya sekali per eksekusi kueri induk, bahkan jika itu dirujuk lebih dari sekali oleh kueri induk atau saudara kueri DENGAN queri.

Saya melihat itu WITHdapat digunakan untuk hal-hal lain, seperti evaluasi rekursif. Tetapi dalam contoh di atas, apakah ada perbedaan penting antara menggunakan WITHdan membuat tabel sementara?

Nathan Long
sumber
saat Anda menggunakan CTE untuk membangun kueri, menambahkan kolom lain ke SELECTdalam WITHhanyalah mengetikkan nama dan menjalankan kembali. Sementara dengan meja sementara dibutuhkan DROPdan CREATE. Di sisi lain jika Anda membangun kueri dan Anda akan menggunakan kembali data statis banyak kali - membangun tabel sementara dengan indeks jelas bermanfaat melawan CTE.
Vao Tsun
@ VaoTsun jika digunakan TEMPORARY TABLEdengan ON COMMIT DROPdalam kueri, itu juga hanya masalah memodifikasi kueri dan menjalankan kembali, kan? postgresql.org/docs/9.6/static/sql-createtable.html
Nathan Long

Jawaban:

16

Ada beberapa perbedaan halus, tetapi tidak ada yang drastis:

  • Anda dapat menambahkan indeks pada tabel temp;
  • Tabel temp ada selama umur sesi (atau, jika ON COMMIT DROP, transaksi), WITHyang selalu dibatasi ketat untuk kueri;
  • Jika permintaan memanggil fungsi / prosedur, dapat melihat tabel temp, tapi bisa tidak melihat WITHtabel-ekspresi;
  • Tabel temp menghasilkan VACUUMkarya pada katalog sistem yang WITHtidak, perlu round trip tambahan untuk membuat / mengisinya, dan itu membutuhkan kerja ekstra dalam manajemen cache server, sehingga sedikit kurang efisien.

Secara keseluruhan, Anda harus memilih WITHuntuk temp tabel kecuali Anda tahu Anda akan mendapat manfaat dari membuat indeks.

Namun, opsi lainnya, subquery dalam FROMklausa, memiliki serangkaian keunggulan yang sangat berbeda. Ini dapat digarisbawahi, khususnya, dan kualifikasi dapat ditarik ke atas / ditekan ke bawah. Saya menulis tentang ini di artikel blog terbaru .

Craig Ringer
sumber
Bagaimana dengan tampilan dan tampilan sementara?
CMCDragonkai
1
Agak peralihan tetapi lebih dekat ke tabel temp daripada istilah CTE. Tidak ada indeks. Sesi mencakup. Terlihat oleh fungsi / prosedur. Membutuhkan vakum katalog.
Craig Ringer