Saya menemukan pertanyaan ini di percakapan Twitter dengan Lukas Eder .
Meskipun perilaku yang benar adalah dengan menerapkan klausa ORDER BY pada kueri terluar, karena, di sini, kami tidak menggunakan DISTINCT, GROUP BY, JOIN, atau klausa WHERE lainnya dalam kueri terluar, mengapa RDBMS tidak akan meneruskan saja data yang masuk karena diurutkan berdasarkan permintaan dalam?
SELECT *
FROM (
SELECT * FROM table ORDER BY time DESC
) AS t
Saat menjalankan contoh ini di PostgreSQL, setidaknya, Anda mendapatkan Paket Eksekusi yang sama untuk kueri dalam dan contoh tabel turunan ini, serta set hasil yang sama.
Jadi, saya akan berasumsi bahwa Perencana hanya akan membuang permintaan terluar karena itu berlebihan atau hanya melewati hasil dari tabel dalam.
Adakah yang mengira ini bukan masalahnya?
mysql
postgresql
oracle
order-by
derived-tables
Vlad Mihalcea
sumber
sumber
ORDER BY
lead untuk pengoptimalan yang berbeda untuk maks groupwise .Jawaban:
Sebagian besar basis data cukup jelas tentang fakta bahwa suatu
ORDER BY
subquery adalah:TOP
atauOFFSET .. FETCH
)OFFSET .. FETCH
atauLIMIT
)Berikut adalah contoh dari manual LU2 DB2 (tambang penekanan)
Kata-katanya cukup eksplisit, seperti halnya PostgreSQL :
Dari spesifikasi ini, dapat dipastikan bahwa setiap pemesanan yang dihasilkan dari
ORDER BY
klausa dalam tabel turunan hanyalah kebetulan dan mungkin secara kebetulan cocok dengan pemesanan yang Anda harapkan (yang dilakukannya di sebagian besar database dalam contoh sepele Anda), tetapi tidak bijaksana untuk mengandalkan ini.Catatan tentang DB2:
Secara khusus, DB2 memiliki fitur yang kurang dikenal
ORDER BY ORDER OF <table-designator>
, yang dapat digunakan sebagai berikut:Dalam kasus khusus ini, urutan tabel turunan dapat secara eksplisit digunakan kembali di paling luar SELECT
Catatan tentang Oracle:
Selama bertahun-tahun telah menjadi praktik di Oracle untuk mengimplementasikan
OFFSET
pagination menggunakanROWNUM
, yang dapat dihitung secara wajar hanya setelah memesan tabel turunan:Dapat diperkirakan bahwa setidaknya dengan adanya
ROWNUM
permintaan, versi Oracle di masa depan tidak akan merusak perilaku ini agar tidak merusak hampir semua warisan Oracle SQL di luar sana, yang belum bermigrasi ke tempat yang jauh lebih diinginkan dan lebih disukai.OFFSET .. FETCH
Sintaks standar SQL yang dapat dibaca :sumber
Meaningless: E.g. PostgreSQL
harus benar-benar: 'diandalkan', karena tidak berarti sesuatu. Baris diurutkan dalam kueri dalam, dan urutan itu disimpan dalam tingkat kueri luar kecuali diinstruksikan sebaliknya atau pemesanan ulang adalah tepat untuk operasi tambahan. Bahkan jika itu hanya detail implementasi, itu tidak berarti. Ini dapat digunakan untuk input yang diurutkan ke fungsi agregat. Manual bahkan mengisyaratkan sebanyak:Alternatively, supplying the input values from a sorted subquery will usually work.
ORDER BY
sama sekali.Iya. Tanpa
ORDER BY
klausa, urutan output tidak ditentukan dan perencana kueri berada dalam jangkauannya untuk mengasumsikan bahwa Anda mengetahui dan memahami hal ini.Mungkin memutuskan bahwa karena kueri luar tidak menentukan pesanan, ia dapat menjatuhkan pemesanan dalam kueri batin untuk menghindari operasi pengurutan, terutama jika tidak ada indeks berkerumun atau tidak ada indeks sama sekali untuk mendukung pemesanan. Jika tidak sekarang dapat dilakukan di versi mendatang.
Jangan pernah mengandalkan perilaku yang tidak terdefinisi. Jika Anda membutuhkan pemesanan khusus, berikan
ORDER BY
klausa di tempat yang sesuai.sumber
TOP 100%
sehingga permintaan saat ini tidak portabel, jika itu menjadi prioritas untuk proyek Anda. Karena Postgres mematuhi pemesanan dalam permintaan dalam sekarang tidak menyiratkan itu akan selalu akan dilakukan di masa depan (atau bahwa versi yang lebih lama melakukannya, pada kenyataannya) sehingga Anda harus menghindari mengandalkan perilaku untuk berjaga-jaga.ORDER BY
adalah MariaDB: Mengapa ORDER BY dalam FROM Subquery Diabaikan?Ini adalah masalah dengan perilaku yang tidak terdefinisi - bekerja untuk Anda, bekerja untuk saya, memformat ulang HDD dalam prod;)
Kita dapat mengambil satu langkah mundur dan mengatakan bahwa dalam satu hal Anda benar - tidak ada alasan duniawi mengapa setiap RDBMS yang waras akan mengatur ulang baris-baris pada pemilihan dalam. Tapi itu tidak dijamin - artinya di masa depan mungkin ada alasan, dan vendor bebas untuk melakukannya. Berarti bahwa setiap kode yang bergantung pada perilaku ini adalah pada belas kasihan dari perubahan yang dapat dibuat oleh vendor yang mereka tidak wajib mempublikasikan, karena itu bukan merupakan perubahan yang melanggar dari POV API.
sumber
SELECT
tanpaORDER BY
benar-benar tidak deterministik, dan bukan hanya dalam teori atau karena data berubah.)Jawaban untuk semua versi Postgres yang saat ini ada (yang Anda uji) adalah: Tidak - untuk kueri khusus ini. Urutan pesanan dijamin.
Orang-orang SQL server akan merasa tidak nyaman dengan ini karena Microsoft bahkan tidak mengizinkan
ORDER BY
dalam subqueries. Urutan sortir dijamin untuk permintaan sederhana ini di Postgres.ORDER BY
diterapkan dalam subquery, dan kueri luar tidak melakukan apa pun yang dapat mengubah urutan.Manual ini bahkan mengisyaratkan sebanyak dalam bab Fungsi Agregat :
Perhatikan ini hanya benar sementara tingkat kueri luar tidak menambahkan operasi yang dapat mengubah urutan. Jadi itu hanya "dijamin" untuk kasus sederhana, dan itu tidak didukung oleh standar SQL. Postgres bebas untuk memesan ulang jika layak untuk operasi tambahan. Jika ragu tambahkan yang lain
ORDER BY
ke luarSELECT
. (Dalam hal ini bagian dalamnyaORDER BY
akan menjadi noise yang berlebihan untuk permintaan sederhana ini.)sumber
"table"
itu bukan tabel dasar yang sederhana tetapi tampilan kompleks atau tabel dipartisi? Apakah benar ketika rencana juga dieksekusi secara paralel? Apakah benar di Postgres 10 juga? (Saya hanya bertanya, saya tidak yakin untuk jawaban dari semua pertanyaan ini.)