Pengenalan | Dalam persekitaran pangkalan data yang dioptimumkan oleh DBA, kebanyakan masalah prestasi sebenarnya disebabkan oleh penulisan SQL yang tidak betul. Dunia SQL penuh dengan keajaiban Hari ini kita akan melihat SQL pembunuh yang akan membuatkan anda ingin muntah darah. |
Untuk pelanggan insurans, ETL mengambil masa beberapa jam Kami membuat laporan SQL dan mendapati bahawa tekanan adalah terutamanya pada salah satu SQL.
Masa pelaksanaan tunggal: 5788 (saat)
Bacaan logik tunggal: 1 bilion (blok)
Bilangan baris yang dikembalikan pada satu masa: 210,000 (baris)
Mari kita lihat kenyataan SQL dahulu Kerana ia agak panjang, kami hanya memetik sebahagian daripadanya di sini
Lihat pelan pelaksanaannya:
Kami memberi tumpuan terutamanya pada baris 7 hingga 16: kami mendapati terdapat dua imbasan jadual penuh. Penapis telah dilakukan di tengah.
Pengalaman bertahun-tahun memberitahu saya bahawa Penapis yang terdiri daripada dua imbasan jadual penuh mempunyai masalah yang serius kerana ia melibatkan pemprosesan data satu demi satu. Dalam pelan pelaksanaan ini, jadual didorong masih diimbas secara keseluruhannya.
Operasi Tidak Dalam/Dalam kadangkala menghasilkan operasi Penapis Dalam versi sebelum 11g, penyataan tidak dalam mesti ditukar menjadi anti-cantum dalam penyata Limit, jika tidak, anda hanya boleh menggunakan Penapis untuk menapis satu persatu.
Mari kita berikan contoh:
Didapati bahawa tiada sekatan tidak batal pada tiga lajur.
Kami berpura-pura menjadi pengoptimum 10G pada masa ini.
SQL> set alter session optimizer_features_enable=”10.2.0.5″;
Laksanakan SQL berikut:
SQL> set autotracetrace exp
SQL> PILIH * DARI T_TABLE DI MANA JADUAL_NAME TIDAK MASUK(PILIH OBJECT_NAME DARI T_OBJ);
Melihat pelan pelaksanaan pada masa ini, kami mendapati penapis digunakan:
Tetapi dalam versi 11g, pengoptimum secara automatik boleh menukar Tidak beroperasi daripada Penapis mahal kepada Null-Aware-Anti-Join.
Jika anda menambah syarat Bukan nol atau menetapkan atribut medan kepada bukan nolSQL> ubah jadual T_OBJ ubah suai(OBJECT_NAME BUKAN NULL);
Lakukan kenyataan yang sama sekali lagi:
SQL> PILIH * DARI T_TABLE DI MANA TABLE_NAME
TIDAK MASUK(PILIH OBJECT_NAME DARI T_OBJ
WHEREOBJECT_NAME BUKAN NULL);
Lihat pelan pelaksanaan sekali lagi:
Pada masa ini kami mendapati bahawa dalam rancangan pelaksanaan, hash sertai anti.
Dan, dalam 11g, tidak dalam lajur dibenarkan tanpa sekatan tidak batal, dan Anti-Join juga boleh ditukar.
SQL> set alter session optimizer_features_enable=”11.2.0.4″;
SQL> ubah jadual T_OBJ ubah suai(OBJECT_NAME NULL);
SQ> PILIH * DARI T_TABLE DI MANA MEJA_NAME
TIDAK MASUK (PILIH_NAMA_OBJEK DARI T_OBJ);
Lihat pelan pelaksanaan:
Kami melihat bahawa pada masa ini, hash join anti.
juga digunakan tanpa sekatan yang tidak kosong.
Ciri ini boleh dikawal melalui parameter pengoptimum.SQL>ubah set sesi “_optimizer_null_aware_antijoin”=SALAH;
Laksanakan kenyataan di atas sekali lagi dan lihat pelan pelaksanaan:
SQL> PILIH * DARI T_TABLE DI MANA TABLE_NAME
TIDAK MASUK (PILIH_NAMA_OBJEK DARI T_OBJ);
Saya dapati saya masih menggunakan hash join anti.
Telah disahkan bahawa ia tidak menjadi masalah dengan tetapan parameter ini
Logik
Not in ialah pengecualian bersama antara set hasil Sebenarnya, terdapat banyak cara untuk menulis semula, seperti:—Tidak wujud
— Sambungan Luar + adalah batal
—Tolak
Perbezaan antara
not in dan tiga cara penulisan di atas ialah: not in akan mengecualikan nilai nol.
Kami cuba menulis semula.
Kemudian apabila anda fikir keajaiban akan berlaku, kenyataan itu melaporkan ralat!
Mengapa ralat dilaporkan?
Jika kita menukar kenyataan ini kepada bukan dalam:
Mengikut logik tidak masuk, 'A.' perlu ditambah sebelum kod_bayaran pada masa ini, ini tidak menjadi masalah, tetapi jika anda melihat kenyataan ini lagi, ia akan menjadi:
Memandangkan tiada medan FEE_CODE dalam TMP_APP_xxx_PREM A, Not in tidak boleh ditukar secara automatik kepada Null Aware ANTI JOIN.
Jadi, kini jawapannya terbongkar, ternyata satu kesilapan? ! Saya meneka permulaan, tetapi tidak berakhir.
Tetapi dalam kes ini, kerana tiada pernyataan eksplisit dalam pernyataan SQL, ralat ini tidak pernah ditemui semasa proses analisis awal.
Adakah anda juga tidak berkata-kata? Sebenarnya, apa yang saya ingin tanyakan lagi, adakah anda sering menulis SQL pembunuh Tetapi tidak mengapa jika anda sakit, saya ada ubat. (Muka tidak bersalah, jangan pukul saya)
Kita semua tahu bahawa dalam persekitaran pangkalan data yang dioptimumkan oleh DBA, sebahagian besar masalah prestasi sebenarnya disebabkan oleh penulisan SQL yang tidak betul.
Untuk sistem yang tidak dalam talian, melalui audit dan kawalan SQL awal, 80% masalah SQL akan dihapuskan dalam peringkat tunas Bagi sistem berjalan dalam talian, masalah prestasi yang berpotensi boleh ditemui dan diselesaikan untuk mengelakkannya dalam tunas.
Audit SQL membolehkan DBA berubah daripada doktor kecemasan sistem kepada doktor penjagaan kesihatan sistem
1 DBA mengambil bahagian dalam pembangunan kod aplikasi dan proses ujian: Sediakan pembangun dengan cadangan pembangunan pangkalan data profesional dan pengoptimuman
2 Optimumkan bahagian hadapan: Reka bentuk SQL dan indeks yang cekap mengikut keperluan perniagaan sebelum kod aplikasi masuk dalam talian
3. Kawal risiko perubahan: Pra-nilai kesan perubahan struktur jadual dan perubahan SQL semasa pembangunan aplikasi pada aplikasi yang sedang dijalankan, dan tentukan tetingkap perubahan yang sesuai dan pelan perubahan.
Atas ialah kandungan terperinci Optimumkan pertanyaan SQL untuk mengurangkan masa jalan 'Tidak dalam'. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!