Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
SQLkonstruksi untuk kueri paralel di Aurora My SQL
Di bagian berikut, Anda dapat menemukan detail lebih lanjut tentang mengapa SQL pernyataan tertentu menggunakan atau tidak menggunakan query paralel. Bagian ini juga merinci bagaimana SQL fitur Aurora My berinteraksi dengan query paralel. Informasi ini dapat membantu Anda mendiagnosis masalah performa untuk klaster yang menggunakan kueri paralel atau memahami cara kueri paralel berlaku untuk beban kerja tertentu Anda.
Keputusan untuk menggunakan kueri paralel bergantung pada banyak faktor yang terjadi pada saat pernyataan itu berjalan. Dengan demikian, kueri paralel dapat digunakan untuk kueri tertentu selalu, tidak pernah, atau hanya dalam kondisi tertentu.
Tip
Ketika Anda melihat contoh-contoh ini diHTML, Anda dapat menggunakan widget Salin di sudut kanan atas setiap daftar kode untuk menyalin kode untuk mencoba SQL sendiri. Dengan menggunakan widget Salin, Anda tidak perlu menyalin karakter tambahan di sekitar prompt mysql>
dan baris lanjutan ->
.
Topik
- EXPLAINpernyataan
- Klausul WHERE
- Bahasa definisi data (DDL)
- Jenis data kolom
- Tabel yang dipartisi
- Fungsi agregat, klausa GROUP BY, dan klausa HAVING
- Panggilan fungsi dalam WHERE klausa
- Klausul LIMIT
- Operator perbandingan
- Gabungan
- Subkueri
- UNION
- Tampilan
- Pernyataan bahasa manipulasi data (DML)
- Transaksi dan penguncian
- Indeks pohon B
- Indeks pencarian teks lengkap (FTS)
- Kolom virtual
- Mekanisme caching default
- Petunjuk pengoptimal
- Meja ISAM sementara saya
EXPLAINpernyataan
Seperti yang ditunjukkan dalam contoh di seluruh bagian ini, pernyataan EXPLAIN
menunjukkan apakah setiap tahap kueri saat ini memenuhi syarat untuk kueri paralel. Pernyataan itu juga menunjukkan aspek mana dari kueri yang dapat diturunkan ke lapisan penyimpanan. Berikut ini adalah item terpenting dalam rencana kueri:
-
Nilai selain
NULL
untuk kolomkey
menunjukkan bahwa kueri dapat dilakukan secara efisien menggunakan pencarian indeks, dan kueri paralel tidak memungkinkan. -
Nilai kecil untuk kolom
rows
(nilai bukan dalam jutaan) menunjukkan bahwa kueri tersebut tidak mengakses cukup data untuk membuat kueri paralel yang bermanfaat. Ini berarti kueri paralel tidak memungkinkan. -
Kolom
Extra
menunjukkan jika kueri paralel yang diharapkan akan digunakan. Output ini terlihat seperti contoh berikut.Using parallel query (
A
columns,B
filters,C
exprs;D
extra)Angka
columns
menunjukkan jumlah kolom yang dimaksud dalam blok kueri.Angka
filters
menunjukkan jumlah predikatWHERE
yang menunjukkan perbandingan sederhana antara nilai kolom dan konstanta. Perbandingannya dapat berupa kesetaraan, ketidaksetaraan, atau rentang. Aurora dapat memaralelkan jenis predikat ini dengan sangat efektif.Angka
exprs
menunjukkan jumlah ekspresi seperti panggilan fungsi, operator, atau ekspresi lainnya yang juga dapat diparalelkan, meskipun tidak sama efektifnya dengan ketentuan filter.Angka
extra
menunjukkan jumlah ekspresi yang tidak dapat diturunkan dan dilakukan oleh simpul kepala.
Contohnya, pertimbangkan output EXPLAIN
berikut ini.
mysql>
explain select p_name, p_mfgr from part->
where p_brand is not null->
and upper(p_type) is not null->
and round(p_retailprice) is not null;+----+-------------+-------+...+----------+----------------------------------------------------------------------------+ | id | select_type | table |...| rows | Extra | +----+-------------+-------+...+----------+----------------------------------------------------------------------------+ | 1 | SIMPLE | part |...| 20427936 | Using where; Using parallel query (5 columns, 1 filters, 2 exprs; 0 extra) | +----+-------------+-------+...+----------+----------------------------------------------------------------------------+
Informasi dari kolom Extra
menunjukkan bahwa lima kolom diekstraksi dari setiap baris untuk mengevaluasi ketentuan kueri dan menyusun set hasil. Satu predikat WHERE
mencakup sebuah filter, yaitu, kolom yang langsung diuji dalam klausa WHERE
. Dua klausa WHERE
memerlukan evaluasi ekspresi yang lebih rumit, dalam hal ini mencakup panggilan fungsi. Bidang 0 extra
mengonfirmasi bahwa semua operasi dalam klausa WHERE
diturunkan ke lapisan penyimpanan sebagai bagian dari pemrosesan kueri paralel.
Dalam kasus di mana kueri paralel tidak dipilih, Anda biasanya dapat menyimpulkan alasan dari output kolom EXPLAIN
lain. Contohnya, nilai rows
mungkin terlalu kecil, atau kolom possible_keys
mungkin menunjukkan bahwa kueri dapat menggunakan pencarian indeks alih-alih pemindaian sarat data. Contoh berikut menunjukkan sebuah kueri di mana pengoptimal dapat memperkirakan bahwa kueri tersebut hanya akan memindai sejumlah kecil baris. Hal itu dilakukan berdasarkan karakteristik kunci primer. Dalam hal ini, kueri paralel tidak diperlukan.
mysql>
explain select count(*) from part where p_partkey between 1 and 100;+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+ | 1 | SIMPLE | part | range | PRIMARY | PRIMARY | 4 | NULL | 99 | Using where; Using index | +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
Output yang menunjukkan apakah kueri paralel akan digunakan mempertimbangkan semua faktor yang tersedia saat pernyataan EXPLAIN
dijalankan. Pengoptimal mungkin mengambil pilihan lain saat kueri benar-benar dijalankan, jika situasi berubah pada saat itu. Contohnya, EXPLAIN
dapat melaporkan bahwa suatu pernyataan akan menggunakan kueri paralel. Namun saat kueri benar-benar dijalankan nantinya, kueri tersebut mungkin tidak menggunakan kueri paralel berdasarkan kondisi pada saat itu. Kondisi tersebut dapat mencakup beberapa kueri paralel lainnya yang berjalan secara serentak. Kondisi lainnya juga dapat mencakup baris yang dihapus dari tabel, indeks baru yang dibuat, terlalu banyak waktu yang terlewati dalam transaksi terbuka, dan sebagainya.
Klausul WHERE
Agar menggunakan pengoptimalan kueri paralel, suatu kueri harus mencakup klausa WHERE
.
Pengoptimalan kueri paralel mempercepat berbagai jenis ekspresi yang digunakan dalam klausa WHERE
:
-
Perbandingan sederhana antara nilai kolom dengan konstanta, yang disebut filter. Perbandingan ini sangat diuntungkan ketika diturunkan ke lapisan penyimpanan. Jumlah ekspresi filter dalam sebuah kueri dilaporkan dalam output
EXPLAIN
. -
Jenis ekspresi lain dalam klausa
WHERE
juga diturunkan ke lapisan penyimpanan jika memungkinkan. Jumlah ekspresi tersebut dalam sebuah kueri dilaporkan dalam outputEXPLAIN
. Ekspresi ini dapat berupa panggilan fungsi, operatorLIKE
, ekspresiCASE
, dan sebagainya. -
Fungsi dan operator tertentu saat ini tidak diturunkan oleh kueri paralel. Jumlah ekspresi tersebut dalam sebuah kueri dilaporkan sebagai penghitung
extra
dalam outputEXPLAIN
. Sisa kueri tersebut masih dapat menggunakan kueri paralel. -
Meskipun ekspresi dalam daftar pilihan tidak diturunkan, kueri yang berisi fungsi tersebut masih dapat diuntungkan dari pengurangan lalu lintas jaringan untuk hasil perantara dari kueri paralel. Contohnya, kueri yang memanggil fungsi agregat dalam daftar pilihan dapat diuntungkan dari kueri paralel, meskipun fungsi agregasi tidak diturunkan.
Contohnya, kueri berikut ini melakukan pemindaian tabel lengkap dan memproses semua nilai untuk kolom P_BRAND
. Akan tetapi, kueri tersebut tidak menggunakan kueri paralel karena tidak mencakup klausa WHERE
apa pun.
mysql>
explain select count(*), p_brand from part group by p_brand;+----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+ | 1 | SIMPLE | part | ALL | NULL | NULL | NULL | NULL | 20427936 | Using temporary; Using filesort | +----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+
Sebaliknya, kueri berikut mencakup predikat WHERE
yang memfilter hasil, sehingga kueri paralel dapat diterapkan:
mysql>
explain select count(*), p_brand from part where p_name is not null->
and p_mfgr in ('Manufacturer#1', 'Manufacturer#3') and p_retailprice > 1000->
group by p_brand;+----+...+----------+-------------------------------------------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+-------------------------------------------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using temporary; Using filesort; Using parallel query (5 columns, 1 filters, 2 exprs; 0 extra) | +----+...+----------+-------------------------------------------------------------------------------------------------------------+
Jika pengoptimal memperkirakan bahwa baris yang dikembalikan untuk suatu blok kueri jumlahnya kecil, kueri paralel tidak digunakan untuk blok kueri tersebut. Contoh berikut menunjukkan kasus di mana operator lebih-besar-daripada di kolom kunci primer berlaku untuk jutaan baris, yang menyebabkan kueri paralel digunakan. Pengujian kurang-dari yang berkebalikan diperkirakan berlaku hanya pada beberapa baris dan tidak menggunakan kueri paralel.
mysql>
explain select count(*) from part where p_partkey > 10;+----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------+----------------------------------------------------------------------------+
mysql>
explain select count(*) from part where p_partkey < 10;+----+...+------+--------------------------+ | id |...| rows | Extra | +----+...+------+--------------------------+ | 1 |...| 9 | Using where; Using index | +----+...+------+--------------------------+
Bahasa definisi data (DDL)
Di Aurora My SQL versi 2, query paralel hanya tersedia untuk tabel yang tidak ada operasi bahasa definisi data cepat (DDL) yang tertunda. Di Aurora My SQL versi 3, Anda dapat menggunakan query paralel pada tabel pada saat yang sama sebagai operasi instanDDL.
Instan DDL di Aurora SQL Versi saya 3 menggantikan fitur cepat DDL di Aurora My versi 2. SQL Untuk informasi tentang instanDDL, lihatDDL instan (Aurora MySQL versi 3).
Jenis data kolom
Di Aurora My SQL versi 3, query paralel dapat bekerja dengan tabel yang berisi kolom dengan tipe dataTEXT
,, BLOB
JSON
, dan. GEOMETRY
Ini juga dapat bekerja dengan kolom VARCHAR
dan CHAR
dengan panjang maksimum yang dinyatakan melebihi 768 byte. Jika kueri Anda mengacu pada kolom yang berisi jenis objek besar seperti itu, tugas tambahan untuk mengambilnya akan memunculkan overhead ke dalam pemrosesan kueri. Dalam hal ini, periksa apakah kueri dapat menghilangkan referensi ke kolom-kolom tersebut. Jika tidak, jalankan tolok ukur untuk mengonfirmasi apakah kueri tersebut lebih cepat dengan kueri paralel diaktifkan atau dinonaktifkan.
Di Aurora My SQL versi 2, query paralel memiliki batasan ini untuk tipe objek besar:
-
Jenis data
TEXT
,BLOB
,JSON
, danGEOMETRY
tidak didukung dengan kueri paralel. Kueri yang mengacu pada kolom apa pun dari jenis ini tidak dapat menggunakan kueri paralel. -
Kolom dengan panjang variabel (jenis data
VARCHAR
danCHAR
) kompatibel dengan kueri paralel hingga panjang maksimum yang dinyatakan 768 byte. Kueri yang mengacu pada kolom apa pun dari jenis yang dinyatakan dengan panjang maksimum yang lebih panjang tidak dapat menggunakan kueri paralel. Untuk kolom yang menggunakan set karakter multibyte, batas byte mempertimbangkan jumlah maksimum byte dalam set karakter. Contohnya, untuk set karakterutf8mb4
(yang memiliki panjang karakter maksimum 4 byte), kolomVARCHAR(192)
kompatibel dengan kueri paralel tetapi kolomVARCHAR(193)
tidak.
Tabel yang dipartisi
Anda dapat menggunakan tabel yang dipartisi dengan query paralel di Aurora My versi 3. SQL Karena tabel yang dipartisi direpresentasikan secara internal sebagai beberapa tabel yang lebih kecil, kueri yang menggunakan kueri paralel pada tabel yang tidak dipartisi mungkin tidak menggunakan kueri paralel pada tabel yang dipartisi identik. Aurora My SQL mempertimbangkan apakah setiap partisi cukup besar untuk memenuhi syarat untuk optimasi query paralel, alih-alih mengevaluasi ukuran seluruh tabel. Periksa apakah variabel status Aurora_pq_request_not_chosen_small_table
bertambah jika kueri pada tabel yang dipartisi tidak menggunakan kueri paralel padahal Anda mengharapkannya.
Misalnya, pertimbangkan satu tabel yang dipartisi dengan PARTITION BY HASH (
dan tabel lain dipartisi dengan column
) PARTITIONS 2PARTITION BY HASH (
. Dalam tabel dengan dua partisi, partisinya lima kali lebih besar daripada tabel dengan sepuluh partisi. Dengan demikian, kueri paralel lebih memungkinkan untuk digunakan untuk mengueri tabel dengan lebih sedikit partisi. Dalam contoh berikut, tabel column
) PARTITIONS 10PART_BIG_PARTITIONS
memiliki dua partisi dan PART_SMALL_PARTITIONS
memiliki sepuluh partisi. Dengan data yang identik, kueri paralel lebih memungkinkan untuk digunakan untuk tabel dengan lebih sedikit partisi besar.
mysql> explain select count(*), p_brand from part_big_partitions where p_name is not null -> and p_mfgr in ('Manufacturer#1', 'Manufacturer#3') and p_retailprice > 1000 group by p_brand; +----+-------------+---------------------+------------+-------------------------------------------------------------------------------------------------------------------+ | id | select_type | table | partitions | Extra | +----+-------------+---------------------+------------+-------------------------------------------------------------------------------------------------------------------+ | 1 | SIMPLE | part_big_partitions | p0,p1 | Using where; Using temporary; Using parallel query (4 columns, 1 filters, 1 exprs; 0 extra; 1 group-bys, 1 aggrs) | +----+-------------+---------------------+------------+-------------------------------------------------------------------------------------------------------------------+ mysql> explain select count(*), p_brand from part_small_partitions where p_name is not null -> and p_mfgr in ('Manufacturer#1', 'Manufacturer#3') and p_retailprice > 1000 group by p_brand; +----+-------------+-----------------------+-------------------------------+------------------------------+ | id | select_type | table | partitions | Extra | +----+-------------+-----------------------+-------------------------------+------------------------------+ | 1 | SIMPLE | part_small_partitions | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9 | Using where; Using temporary | +----+-------------+-----------------------+-------------------------------+------------------------------+
Fungsi agregat, klausa GROUP BY, dan klausa HAVING
Kueri yang mencakup fungsi agregat sering kali merupakan kandidat yang baik untuk kueri paralel, karena kueri tersebut memindai baris dalam jumlah besar dalam tabel besar.
Di Aurora My SQL 3, query paralel dapat mengoptimalkan panggilan fungsi agregat dalam daftar pilih dan klausa. HAVING
Sebelum Aurora My SQL 3, panggilan fungsi agregat dalam daftar pilih atau HAVING
klausa tidak ditekan ke lapisan penyimpanan. Akan tetapi, kueri paralel tetap dapat meningkatkan performa kueri dengan fungsi agregat tersebut. Hal itu dilakukan pertama-tama dengan mengekstraksi nilai kolom dari halaman data mentah secara paralel pada lapisan penyimpanan. Kueri paralel tersebut kemudian mengirim kembali nilai itu ke simpul kepala dalam format urutan yang padat, bukan sebagai keseluruhan halaman data. Seperti biasa, kueri memerlukan setidaknya satu predikat WHERE
agar kueri paralel dapat diaktifkan.
Contoh sederhana berikut mengilustrasikan jenis kueri agregat yang dapat diuntungkan dari kueri paralel. Hal tersebut dilakukan dengan mengembalikan hasil menengah dalam bentuk ringkas ke simpul kepala, memfilter baris yang tidak cocok dari hasil menengah, atau keduanya.
mysql>
explain select sql_no_cache count(distinct p_brand) from part where p_mfgr = 'Manufacturer#5';+----+...+----------------------------------------------------------------------------+ | id |...| Extra | +----+...+----------------------------------------------------------------------------+ | 1 |...| Using where; Using parallel query (2 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------------------------------------------------------------------------+
mysql>
explain select sql_no_cache p_mfgr from part where p_retailprice > 1000 group by p_mfgr having count(*) > 100;+----+...+-------------------------------------------------------------------------------------------------------------+ | id |...| Extra | +----+...+-------------------------------------------------------------------------------------------------------------+ | 1 |...| Using where; Using temporary; Using filesort; Using parallel query (3 columns, 0 filters, 1 exprs; 0 extra) | +----+...+-------------------------------------------------------------------------------------------------------------+
Panggilan fungsi dalam WHERE klausa
Aurora dapat menerapkan pengoptimalan kueri paralel pada panggilan ke sebagian besar fungsi default dalam klausa WHERE
. Memparalelkan panggilan fungsi ini menurunkan beberapa CPU pekerjaan dari node kepala. Mengevaluasi fungsi predikat secara paralel selama tahap kueri paling awal akan membantu Aurora meminimalkan jumlah data yang dikirim dan diproses selama tahap berikutnya.
Saat ini, paralelisasi tidak berlaku untuk panggilan fungsi dalam daftar pilihan. Fungsi-fungsi tersebut dievaluasi oleh simpul kepala, bahkan jika panggilan fungsi yang identik muncul dalam klausa WHERE
. Nilai asli dari kolom yang relevan disertakan dalam urutan yang dikirim dari simpul penyimpanan kembali ke simpul kepala. Simpul kepala melakukan transformasi apa pun seperti UPPER
, CONCATENATE
, dan seterusnya untuk menghasilkan nilai akhir untuk set hasil.
Dalam contoh berikut, kueri paralel memaralelkan panggilan dengan LOWER
karena muncul di klausa WHERE
. Kueri paralel tidak memengaruhi panggilan ke SUBSTR
dan UPPER
karena muncul dalam daftar pilihan.
mysql>
explain select sql_no_cache distinct substr(upper(p_name),1,5) from part->
where lower(p_name) like '%cornflower%' or lower(p_name) like '%goldenrod%';+----+...+---------------------------------------------------------------------------------------------+ | id |...| Extra | +----+...+---------------------------------------------------------------------------------------------+ | 1 |...| Using where; Using temporary; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | +----+...+---------------------------------------------------------------------------------------------+
Pertimbangan yang sama berlaku untuk ekspresi lain, seperti ekspresi CASE
atau operator LIKE
. Misalnya, contoh berikut menunjukkan bahwa kueri paralel mengevaluasi ekspresi CASE
dan operator LIKE
di klausa WHERE
.
mysql>
explain select p_mfgr, p_retailprice from part->
where p_retailprice > case p_mfgr->
when 'Manufacturer#1' then 1000->
when 'Manufacturer#2' then 1200->
else 950->
end->
and p_name like '%vanilla%'->
group by p_retailprice;+----+...+-------------------------------------------------------------------------------------------------------------+ | id |...| Extra | +----+...+-------------------------------------------------------------------------------------------------------------+ | 1 |...| Using where; Using temporary; Using filesort; Using parallel query (4 columns, 0 filters, 2 exprs; 0 extra) | +----+...+-------------------------------------------------------------------------------------------------------------+
Klausul LIMIT
Saat ini, kueri paralel tidak digunakan untuk blok kueri yang mencakup klausa LIMIT
. Kueri paralel masih dapat digunakan untuk fase kueri sebelumnya dengan GROUP
by, ORDER BY
, atau gabungan.
Operator perbandingan
Pengoptimal memperkirakan jumlah baris yang harus dipindai untuk mengevaluasi operator perbandingan, dan menentukan apakah akan menggunakan kueri paralel berdasarkan estimasi tersebut.
Contoh pertama berikut ini menunjukkan bahwa perbandingan setara terhadap kolom kunci primer dapat dilakukan secara efisien tanpa kueri paralel. Contoh kedua berikut menunjukkan bahwa perbandingan yang serupa terhadap kolom yang tidak diindeks memerlukan pemindaian jutaan baris, sehingga dapat diuntungkan dari kueri paralel.
mysql>
explain select * from part where p_partkey = 10;+----+...+------+-------+ | id |...| rows | Extra | +----+...+------+-------+ | 1 |...| 1 | NULL | +----+...+------+-------+
mysql>
explain select * from part where p_type = 'LARGE BRUSHED BRASS';+----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (9 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------+----------------------------------------------------------------------------+
Pertimbangan yang sama berlaku untuk pengujian tidak sama dan untuk perbandingan rentang seperti kurang dari, lebih besar dari, atau sama dengan, atau BETWEEN
. Pengoptimal memperkirakan jumlah baris yang akan dipindai, dan menentukan apakah kueri paralel bermanfaat berdasarkan volume keseluruhan I/O.
Gabungan
Kueri gabungan dengan tabel besar biasanya mencakup operasi sarat data yang diuntungkan dari pengoptimalan kueri paralel. Perbandingan nilai kolom di antara beberapa tabel (yaitu, predikat gabungan itu sendiri) saat ini tidak diparalelkan. Namun, kueri paralel dapat menurunkan beberapa pemrosesan internal untuk fase penggabungan lainnya, seperti membangun filter Bloom selama hash join. Kueri paralel dapat diterapkan pada kueri gabungan tanpa klausa WHERE
. Oleh karena itu, kueri gabungan adalah pengecualian untuk aturan bahwa klausa WHERE
diperlukan untuk menggunakan kueri paralel.
Setiap fase pemrosesan gabungan dievaluasi untuk memeriksa apakah fase tersebut memenuhi syarat untuk kueri paralel. Jika lebih dari satu fase dapat menggunakan kueri paralel, fase-fase ini dilakukan secara berurutan. Dengan demikian, setiap kueri gabungan dihitung sebagai satu sesi kueri paralel dalam hal batas keserentakan.
Contohnya, saat kueri gabungan mencakup predikat WHERE
untuk memfilter baris dari salah satu tabel yang digabungkan, opsi pemfilteran tersebut dapat menggunakan kueri paralel. Sebagai contoh lain, anggaplah kueri gabungan menggunakan mekanisme hash join, contohnya untuk menggabungkan tabel besar dengan tabel kecil. Dalam hal ini, pemindaian tabel untuk menghasilkan struktur data filter Bloom mungkin dapat menggunakan kueri paralel.
catatan
Kueri paralel biasanya digunakan untuk jenis kueri sarat sumber daya yang diuntungkan dari pengoptimalan hash join. Metode untuk mengaktifkan optimasi bergabung hash tergantung pada versi Aurora MySQL. Untuk detail untuk setiap versi, lihat Mengaktifkan hash join untuk klaster kueri paralel. Untuk informasi tentang cara menggunakan hash join secara efektif, lihat Mengoptimalkan Aurora besar Kueri bergabung SQL saya dengan gabungan hash.
mysql>
explain select count(*) from orders join customer where o_custkey = c_custkey;+----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+ | id |...| table | type | possible_keys | key |...| rows | Extra | +----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+ | 1 |...| customer | index | PRIMARY | c_nationkey |...| 15051972 | Using index | | 1 |...| orders | ALL | o_custkey | NULL |...| 154545408 | Using join buffer (Hash Join Outer table orders); Using parallel query (1 columns, 0 filters, 1 exprs; 0 extra) | +----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+
Untuk kueri gabungan yang menggunakan mekanisme nested loop, blok nested loop terluar mungkin menggunakan kueri paralel. Penggunaan kueri paralel bergantung pada faktor yang sama seperti biasanya, seperti adanya ketentuan filter tambahan dalam klausa WHERE
.
mysql>
-- Nested loop join with extra filter conditions can use parallel query.mysql>
explain select count(*) from part, partsupp where p_partkey != ps_partkey and p_name is not null and ps_availqty > 0;+----+-------------+----------+...+----------+----------------------------------------------------------------------------+ | id | select_type | table |...| rows | Extra | +----+-------------+----------+...+----------+----------------------------------------------------------------------------+ | 1 | SIMPLE | part |...| 20427936 | Using where; Using parallel query (2 columns, 1 filters, 0 exprs; 0 extra) | | 1 | SIMPLE | partsupp |...| 78164450 | Using where; Using join buffer (Block Nested Loop) | +----+-------------+----------+...+----------+----------------------------------------------------------------------------+
Subkueri
Blok kueri luar dan blok subkueri dalam masing-masing dapat menggunakan kueri paralel, atau tidak. Untuk setiap blok, menggunakan kueri paralel atau tidak, didasarkan pada karakteristik umum tabel, klausa WHERE
, dan sebagainya. Contohnya, kueri berikut menggunakan kueri paralel untuk blok subkueri tetapi tidak untuk blok luar.
mysql>
explain select count(*) from part where-->
p_partkey < (select max(p_partkey) from part where p_name like '%vanilla%');+----+-------------+...+----------+----------------------------------------------------------------------------+ | id | select_type |...| rows | Extra | +----+-------------+...+----------+----------------------------------------------------------------------------+ | 1 | PRIMARY |...| NULL | Impossible WHERE noticed after reading const tables | | 2 | SUBQUERY |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | +----+-------------+...+----------+----------------------------------------------------------------------------+
Saat ini, subkueri yang berkorelasi tidak dapat menggunakan pengoptimalan kueri paralel.
UNION
Setiap blok kueri dalam kueri UNION
dapat menggunakan kueri paralel atau tidak, berdasarkan karakteristik umum tabel, klausul WHERE
, dan sebagainya, untuk setiap bagian UNION
.
mysql>
explain select p_partkey from part where p_name like '%choco_ate%'->
union select p_partkey from part where p_name like '%vanil_a%';+----+----------------+...+----------+----------------------------------------------------------------------------+ | id | select_type |...| rows | Extra | +----+----------------+...+----------+----------------------------------------------------------------------------+ | 1 | PRIMARY |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | | 2 | UNION |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | | NULL | UNION RESULT | <union1,2> |...| NULL | Using temporary | +----+--------------+...+----------+----------------------------------------------------------------------------+
catatan
Setiap klausa UNION
dalam kueri dijalankan secara berurutan. Bahkan jika kueri mencakup beberapa tahap yang semuanya menggunakan kueri paralel, kueri tersebut hanya menjalankan satu kueri paralel dalam satu waktu. Oleh karena itu, bahkan kueri multitahap yang kompleks hanya dihitung sebagai 1 terhadap batas kueri paralel yang serentak.
Tampilan
Pengoptimal menulis ulang kueri apa pun menggunakan tampilan sebagai kueri yang lebih panjang menggunakan tabel yang mendasarinya. Dengan demikian, kueri paralel bekerja dengan cara yang sama baik referensi tabelnya berupa tampilan atau tabel nyata. Semua pertimbangan yang sama tentang apakah akan menggunakan kueri paralel untuk suatu kueri, dan bagian mana yang diturunkan, berlaku untuk kueri terakhir yang ditulis ulang.
Contohnya, rencana kueri berikut menunjukkan definisi tampilan yang biasanya tidak menggunakan kueri paralel. Ketika tampilan ditanyakan dengan WHERE
klausa tambahan, Aurora My SQL menggunakan query paralel.
mysql>
create view part_view as select * from part;mysql>
explain select count(*) from part_view where p_partkey is not null;+----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (1 columns, 0 filters, 0 exprs; 1 extra) | +----+...+----------+----------------------------------------------------------------------------+
Pernyataan bahasa manipulasi data (DML)
Pernyataan INSERT
dapat menggunakan kueri paralel untuk fase pemrosesan SELECT
, jika bagian SELECT
sesuai dengan ketentuan lainnya untuk kueri paralel.
mysql>
create table part_subset like part;mysql>
explain insert into part_subset select * from part where p_mfgr = 'Manufacturer#1';+----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (9 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------+----------------------------------------------------------------------------+
catatan
Biasanya, setelah pernyataan INSERT
, data untuk baris yang baru dimasukkan ada di dalam buffer pool. Oleh karena itu, suatu tabel mungkin tidak memenuhi syarat untuk kueri paralel segera setelah memasukkan baris dalam jumlah besar. Lalu, setelah data dikosongkan dari buffer pool selama operasi normal, kueri terhadap tabel tersebut dapat mulai menggunakan kueri paralel.
Pernyataan CREATE TABLE AS SELECT
tidak menggunakan kueri paralel, meskipun bagian SELECT
dari pernyataan tersebut akan memenuhi syarat untuk kueri paralel. DDLAspek pernyataan ini membuatnya tidak kompatibel dengan pemrosesan query paralel. Sebaliknya, dalam pernyataan INSERT ... SELECT
, bagian SELECT
dapat menggunakan kueri paralel.
Kueri paralel tidak pernah digunakan untuk pernyataan DELETE
atau UPDATE
, terlepas dari ukuran tabel dan predikat dalam klausa WHERE
.
mysql>
explain delete from part where p_name is not null;+----+-------------+...+----------+-------------+ | id | select_type |...| rows | Extra | +----+-------------+...+----------+-------------+ | 1 | SIMPLE |...| 20427936 | Using where | +----+-------------+...+----------+-------------+
Transaksi dan penguncian
Anda dapat menggunakan semua tingkat isolasi pada instans utama Aurora.
Pada instans pembaca Aurora DB, kueri paralel berlaku untuk pernyataan yang dilakukan dalam tingkat isolasi REPEATABLE READ
. Aurora SQL Versi saya 2.09 atau lebih tinggi juga dapat menggunakan tingkat READ COMMITTED
isolasi pada instans DB pembaca. REPEATABLE READ
adalah tingkat isolasi default untuk instans DB pembaca Aurora. Untuk menggunakan tingkat isolasi READ
COMMITTED
pada instans reader DB membutuhkan pengaturan opsi konfigurasi aurora_read_replica_read_committed
pada tingkat sesi. Tingkat READ
COMMITTED
isolasi untuk instance pembaca sesuai dengan perilaku SQL standar. Namun, isolasi ini lebih longgar pada instans pembaca dibandingkan ketika kueri menggunakan tingkat isolasi READ COMMITTED
pada instans penulis.
Untuk informasi lebih lanjut tentang tingkat isolasi Aurora, terutama perbedaan dalam hal READ COMMITTED
antara instans penulis dan pembaca, lihat Aurora Tingkat isolasi saya SQL.
Setelah transaksi besar selesai, statistik tabel mungkin menjadi usang. Statistik yang usang tersebut mungkin memerlukan pernyataan ANALYZE TABLE
sebelum Aurora dapat secara akurat memperkirakan jumlah baris. DMLPernyataan skala besar mungkin juga membawa sebagian besar data tabel ke dalam kumpulan buffer. Memiliki data ini di dalam buffer pool dapat menyebabkan kueri paralel menjadi lebih jarang dipilih untuk tabel tersebut sampai data dikosongkan dari pool.
Jika sesi Anda berada dalam transaksi yang berlangsung lama (secara default, 10 menit), kueri lebih lanjut di dalam sesi tersebut tidak menggunakan kueri paralel. Waktu habis juga dapat terjadi dalam satu kueri yang berlangsung lama. Jenis waktu habis ini dapat terjadi jika kueri berjalan lebih lama dari interval maksimum (saat ini 10 menit) sebelum pemrosesan kueri paralel dimulai.
Anda dapat mengurangi kemungkinan memulai transaksi yang berlangsung lama secara tidak sengaja dengan mengatur autocommit=1
dalam sesi mysql
di mana Anda melakukan kueri ad hoc (satu waktu). Bahkan pernyataan SELECT
terhadap suatu tabel akan memulai transaksi dengan membuat tampilan baca. Tampilan baca merupakan rangkaian data yang konsisten untuk kueri berikutnya yang tetap ada hingga transaksi dilakukan. Waspadai pembatasan ini juga saat menggunakan JDBC atau ODBC aplikasi dengan Aurora, karena aplikasi tersebut mungkin berjalan dengan pengaturan autocommit
dimatikan.
Contoh berikut ini menunjukkan bagaimana, dengan pengaturan autocommit
yang dinonaktifkan, menjalankan suatu kueri terhadap tabel akan menciptakan tampilan baca yang secara implisit memulai transaksi. Kueri yang dijalankan segera sesudahnya masih dapat menggunakan kueri paralel. Namun, setelah jeda beberapa menit, kueri tidak lagi memenuhi syarat untuk kueri paralel. Mengakhiri transaksi dengan COMMIT
atau ROLLBACK
akan memulihkan eligilibilitas kueri paralel.
mysql>
set autocommit=0;mysql>
explain select sql_no_cache count(*) from part where p_retailprice > 10.0;+----+...+---------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+---------+----------------------------------------------------------------------------+ | 1 |...| 2976129 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) | +----+...+---------+----------------------------------------------------------------------------+
mysql>
select sleep(720); explain select sql_no_cache count(*) from part where p_retailprice > 10.0;+------------+ | sleep(720) | +------------+ | 0 | +------------+ 1 row in set (12 min 0.00 sec) +----+...+---------+-------------+ | id |...| rows | Extra | +----+...+---------+-------------+ | 1 |...| 2976129 | Using where | +----+...+---------+-------------+
mysql>
commit;mysql>
explain select sql_no_cache count(*) from part where p_retailprice > 10.0;+----+...+---------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+---------+----------------------------------------------------------------------------+ | 1 |...| 2976129 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) | +----+...+---------+----------------------------------------------------------------------------+
Untuk melihat berapa kali kueri tidak memenuhi syarat untuk kueri paralel karena kueri tersebut berada dalam transaksi yang berlangsung lama, periksa variabel status Aurora_pq_request_not_chosen_long_trx
.
mysql>
show global status like '%pq%trx%';+---------------------------------------+-------+ | Variable_name | Value | +---------------------------------------+-------+ | Aurora_pq_request_not_chosen_long_trx | 4 | +-------------------------------+-------+
Setiap pernyataan SELECT
yang memperoleh kunci, seperti sintaks SELECT FOR UPDATE
atau SELECT LOCK IN SHARE MODE
, tidak dapat menggunakan kueri paralel.
Kueri paralel dapat berfungsi untuk tabel yang dikunci oleh pernyataan LOCK TABLES
.
mysql>
explain select o_orderpriority, o_shippriority from orders where o_clerk = 'Clerk#000095055';+----+...+-----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+-----------+----------------------------------------------------------------------------+ | 1 |...| 154545408 | Using where; Using parallel query (3 columns, 1 filters, 0 exprs; 0 extra) | +----+...+-----------+----------------------------------------------------------------------------+
mysql>
explain select o_orderpriority, o_shippriority from orders where o_clerk = 'Clerk#000095055' for update;+----+...+-----------+-------------+ | id |...| rows | Extra | +----+...+-----------+-------------+ | 1 |...| 154545408 | Using where | +----+...+-----------+-------------+
Indeks pohon B
Statistik yang dikumpulkan oleh pernyataan ANALYZE TABLE
membantu pengoptimal untuk memutuskan waktu untuk menggunakan kueri paralel atau pencarian indeks, berdasarkan karakteristik data untuk setiap kolom. Pertahankan statistik terkini dengan menjalankan ANALYZE TABLE
setelah DML operasi yang membuat perubahan besar pada data dalam tabel.
Jika pencarian indeks dapat melakukan kueri secara efisien tanpa pemindaian sarat data, Aurora mungkin menggunakan pencarian indeks. Melakukan hal ini akan menghindari pengeluaran tambahan dari pemrosesan kueri paralel. Terdapat juga batas keserentakan pada jumlah kueri paralel yang dapat berjalan secara bersamaan di klaster Aurora DB mana pun. Pastikan Anda menggunakan praktik terbaik untuk mengindeks tabel, sehingga kueri yang paling sering dan paling sering muncul bersamaan menggunakan pencarian indeks.
Indeks pencarian teks lengkap (FTS)
Saat ini, kueri paralel tidak digunakan untuk tabel yang berisi indeks pencarian teks penuh, terlepas dari apakah kueri tersebut mengacu pada kolom yang diindeks tersebut atau menggunakan operator MATCH
.
Kolom virtual
Saat ini, kueri paralel tidak digunakan untuk tabel yang berisi kolom virtual, terlepas dari apakah kueri tersebut merujuk pada kolom virtual mana pun.
Mekanisme caching default
Aurora mencakup mekanisme caching default, yaitu buffer pool dan cache kueri. Pengoptimal Aurora memilih antara mekanisme caching ini dan kueri paralel bergantung pada mana yang paling efektif untuk kueri tertentu.
Saat kueri paralel memfilter baris dan mengubah serta mengekstraksi nilai kolom, data dikirim kembali ke simpul kepala sebagai urutan dan bukan sebagai halaman data. Oleh karena itu, menjalankan kueri paralel tidak akan menambahkan halaman apa pun ke dalam buffer pool, atau mengosongkan halaman yang sudah ada di dalam buffer pool.
Aurora memeriksa jumlah halaman data tabel yang ada dalam buffer pool, dan bagian mana dari data tabel tersebut yang direpresentasikan oleh angka tersebut. Aurora menggunakan informasi tersebut untuk menentukan apakah lebih efisien untuk menggunakan kueri paralel (dan mem-bypass data dalam buffer pool). Sebagai alternatif, Aurora mungkin menggunakan jalur pemrosesan kueri nonparalel, yang menggunakan cache data dalam buffer pool. Halaman mana yang dibuat cache dan bagaimana kueri sarat data dapat memengaruhi caching dan pengosongan bergantung pada pengaturan konfigurasi yang terkait dengan buffer pool. Oleh karena itu, akan sulit untuk memprediksi apakah kueri tertentu menggunakan kueri paralel, karena pilihannya bergantung pada data yang selalu berubah dalam buffer pool.
Selain itu, Aurora menerapkan batas keserentakan pada kueri paralel. Karena tidak setiap kueri menggunakan kueri paralel, tabel yang diakses oleh beberapa kueri secara serentak biasanya memiliki bagian yang substansial dari datanya dalam buffer pool. Oleh karena itu, Aurora sering kali tidak memilih tabel ini untuk kueri paralel.
Ketika Anda menjalankan urutan kueri nonparalel pada tabel yang sama, kueri pertama mungkin lambat karena data tidak ada dalam buffer pool. Lalu kueri kedua dan selanjutnya jauh lebih cepat karena buffer pool sekarang sudah "dipanaskan". Kueri paralel biasanya menunjukkan performa yang konsisten dari kueri pertama terhadap tabel. Saat melakukan uji performa, buat tolok ukur kueri nonparalel dengan buffer pool yang dingin dan hangat. Dalam beberapa kasus, hasil dari buffer pool hangat dapat menghasilkan perbandingan yang baik dengan waktu kueri paralel. Dalam kasus ini, pertimbangkan faktor seperti frekuensi kueri terhadap tabel tersebut. Pertimbangkan juga apakah bermanfaat untuk menyimpan data untuk tabel tersebut di dalam buffer pool.
Cache kueri menghindari menjalankan ulang kueri saat kueri yang identik dikirimkan dan data tabel yang mendasarinya tidak berubah. Kueri yang dioptimalkan dengan fitur kueri paralel dapat masuk ke cache kueri, yang secara efektif menjadikannya instan saat dijalankan lagi.
catatan
Saat melakukan perbandingan performa, cache kueri dapat menghasilkan jumlah pengaturan waktu yang rendah secara buatan. Oleh karena itu, dalam situasi serupa tolok ukur, Anda dapat menggunakan petunjuk sql_no_cache
. Petunjuk ini mencegah hasil tersebut tersaji dari cache kueri, meskipun kueri yang sama telah dijalankan sebelumnya. Petunjuk segera muncul setelah pernyataan SELECT
dalam kueri. Banyak contoh kueri paralel dalam topik ini mencakup petunjuk ini, untuk menjadikan waktu kueri sebanding antara versi kueri dengan kueri paralel yang diaktifkan dan dinonaktifkan.
Pastikan Anda menghapus petunjuk ini dari sumber Anda saat beralih ke penggunaan kueri paralel untuk produksi.
Petunjuk pengoptimal
Cara lain untuk mengontrol pengoptimal adalah dengan menggunakan petunjuk pengoptimal, yang dapat ditentukan dalam pernyataan individual. Misalnya, Anda dapat mengaktifkan pengoptimalan untuk satu tabel dalam sebuah pernyataan, kemudian mematikan pengoptimalan untuk tabel yang berbeda. Untuk informasi selengkapnya tentang petunjuk ini, lihat Petunjuk Pengoptimal di Manual Referensi
Anda dapat menggunakan SQL petunjuk dengan kueri Aurora SQL My untuk menyempurnakan kinerja. Anda juga dapat menggunakan petunjuk agar rencana eksekusi untuk kueri penting tidak berubah karena kondisi yang tidak dapat diprediksi.
Kami telah memperluas fitur SQL petunjuk untuk membantu Anda mengontrol pilihan pengoptimal untuk paket kueri Anda. Petunjuk ini berlaku untuk kueri yang menggunakan pengoptimalan kueri paralel. Untuk informasi selengkapnya, lihat Aurora Petunjuk saya SQL.
Meja ISAM sementara saya
Pengoptimalan kueri paralel hanya berlaku untuk tabel InnoDB. Karena Aurora My SQL menggunakan My ISAM behind the scenes untuk tabel sementara, fase kueri internal yang melibatkan tabel temporer tidak pernah menggunakan query paralel. Fase kueri ini ditunjukkan oleh Using
temporary
dalam output EXPLAIN
.