Apakah ada cara untuk mengatur alias pada argumen meta_query saat menjalankan get_posts()
? Salah satu pertanyaan saya berkinerja buruk. Untuk mengoptimalkan saya hanya perlu dapat menggunakan kembali tabel bergabung yang sama alih-alih bergabung dalam 3 tabel ketika hanya satu yang diperlukan.
Contoh saya saat ini ...
$args = array(
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => array('puppy', 'kitten'),
'compare' => 'IN',
),
array(
'relation' => 'OR',
array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => 'puppy',
'compare' => '=',
),
array(
'key' => 'abc_color',
'value' => 'pink',
'compare' => '=',
),
),
array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => 'kitten',
'compare' => '=',
),
array(
'key' => 'abc_size',
'value' => 'large',
'compare' => '=',
),
),
),
)
);
get_posts($args);
yang pada dasarnya diterjemahkan ke dalam ...
SELECT posts.* FROM posts
INNER JOIN postmeta ON ( posts.ID = postmeta.post_id )
INNER JOIN postmeta AS mt1 ON ( posts.ID = mt1.post_id )
INNER JOIN postmeta AS mt2 ON ( posts.ID = mt2.post_id )
INNER JOIN postmeta AS mt3 ON ( posts.ID = mt3.post_id )
WHERE 1=1
AND
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
AND
(
(
( mt1.meta_key = 'abc_type' AND mt1.meta_value = 'puppy' )
AND
( mt2.meta_key = 'abc_color' AND mt2.meta_value > 'pink' )
)
OR
(
( mt3.meta_key = 'abc_type' AND mt3.meta_value = 'kitten' )
AND
( mt4.meta_key = 'abc_size' AND mt4.meta_value = 'large' )
)
)
) AND posts.post_type = 'abc_mypost' AND ((posts.post_status = 'publish'))
GROUP BY posts.ID ORDER BY posts.post_title ASC;
Namun, ini menambahkan 2 penggabungan tambahan untuk bidang meta khusus abc_type
dan karena itu kinerja telah mendapat pukulan besar. Apakah ada cara untuk dapat merujuk alias yang sama untuk beberapa argumen meta_query? Pada dasarnya, mt1
dan mt3
sama sekali tidak perlu, saya seharusnya hanya bisa referensi postmeta
tabel pertama yang digunakan dengan yang pertama ( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
. Atau setidaknya jika saya dapat mengatur alias kustom pada masing-masing ini saya bisa referensi itu.
Kueri yang lebih optimal adalah ...
SELECT posts.* FROM posts
INNER JOIN postmeta ON ( posts.ID = postmeta.post_id )
INNER JOIN postmeta AS mt1 ON ( posts.ID = mt1.post_id )
INNER JOIN postmeta AS mt2 ON ( posts.ID = mt2.post_id )
WHERE 1=1
AND
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
AND
(
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value = 'puppy' )
AND
( mt1.meta_key = 'abc_color' AND mt1.meta_value > 'pink' )
)
OR
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value = 'kitten' )
AND
( mt2.meta_key = 'abc_color' AND mt2.meta_value = 'green' )
)
)
) AND posts.post_type = 'abc_mypost' AND ((posts.post_status = 'publish'))
GROUP BY posts.ID ORDER BY posts.post_title ASC;
Pikiran?
sumber
get_posts()
.posts_where
Filter mungkin berguna.Jawaban:
Lihat
meta_query_find_compatible_table_alias
filter yang ditentukan dalamwp-includes/class-wp-meta-query.php
. Dokumentasi filter ini:Kemungkinan fungsi panggil
find_compatible_table_alias
,, mengembalikan false dan dengan demikian kueri membuatmt*
alias. Berikut adalah beberapa kode contoh menggunakan filter ini, meskipun saya pribadi akan menyarankan sesuatu yang sedikit lebih mudah dimengerti. Memodifikasi kueri seperti ini dapat menyebabkan berton-ton sakit kepala dan mungkin tidak terlihat sama sekali di mana kueri semakin kacau, terutama jika Anda membawa pengembang lain di masa depan. Yang mengatakan ...Ini menghasilkan permintaan seperti
sumber
Anda dapat menggunakan
posts_where
danposts_join
memfilter untuk memodifikasi kueri. Ini tidak terlalu elegan, tetapi Anda harus dapat mengacaukan kedua filter ini sehingga sql Anda lebih optimal. Ini agak kasar, tapi saya tidak bisa melihat cara yang lebih baik di kelas WP_Query. Itu tidak mengatakan tidak ada.Mungkin harus ada beberapa pemeriksaan di sana sehingga Anda tidak secara tidak sengaja memodifikasi pertanyaan lain. Itu dibiarkan sebagai latihan untuk pembaca.
sumber
Anda bisa mengoptimalkan kueri dengan menghapus kueri meta pertama karena mubazir, seperti:
Dengan cara ini Anda hanya akan mendapatkan salah satu
pink puppy
ataularge kitten
, seperti yang Anda inginkan, saya percaya.Adapun untuk mengoptimalkan query MySQL internal WordPress, saya percaya Anda harus tetap jelas tentang hal itu karena Anda akan mengekspos diri Anda terhadap kemungkinan efek samping. Anda akan lebih baik mengandalkan fakta bahwa kueri di-cache dan melakukan lebih banyak pemrosesan PHP pada kumpulan data (lebih besar). Saya percaya ini akan mengarah pada kinerja yang lebih baik secara keseluruhan karena bottleneck bukanlah jumlah data yang Anda ekstrak dari database, tetapi kesulitan dengan mana ia dikumpulkan (berapa banyak pertanyaan). PHP cukup cepat karena datang melalui array.
Jadi saya percaya situasi seperti ini lebih cepat, mengingat meta posting di-cache:
sumber
Saya bukan orang yang punya basis data, tapi saya pernah memainkannya di TV ...
Bukankah bagian ini
lebih baik diganti dengan
Itu mungkin dapat disederhanakan bahkan .. dengan beberapa alias terjebak di sana di tempat yang tepat sehingga Anda dapat menggunakan sisa permintaan Anda.
Hanya pemikiran saja...
sumber
get_posts()
, jadi dia tidak menulis kueri sendiri.