Muszę zdobyć kilka postów z ich metadanymi. Oczywiście nie można uzyskać metadanych za pomocą standardowego zapytania do postów, więc na ogół musisz zrobić get_post_custom()
dla każdego postu.
Próbuję z jednym niestandardowym zapytaniem, takim jak to:
$results = $wpdb->get_results("
SELECT p.ID,
p.post_title,
pm1.meta_value AS first_field,
pm2.meta_value AS second_field,
pm3.meta_value AS third_field
FROM $wpdb->posts p LEFT JOIN $wpdb->postmeta pm1 ON (
pm1.post_id = p.ID AND
pm1.meta_key = 'first_field_key'
) LEFT JOIN $wpdb->postmeta pm2 ON (
pm2.post_id = p.ID AND
pm2.meta_key = 'second_field_key'
) LEFT JOIN $wpdb->postmeta pm3 ON (
pm3.post_id = p.ID AND
pm3.meta_key = 'third_field_key'
)
WHERE post_status = 'publish'
");
Wydaje się działać. Występuje, jeśli użyjesz któregokolwiek z tych pól meta w sposób, który pozwala na wiele meta wartości dla tego samego postu. Nie mogę wymyślić takiego połączenia.
Pytanie 1: Czy istnieje sprzężenie, zapytanie cząstkowe lub cokolwiek innego, aby wprowadzić pola meta o wielu wartościach?
Ale pytanie 2: czy warto? Ile postmeta
sprzężeń tabel dodam, zanim podejście z dwoma zapytaniami stanie się preferowane? Mogłem pobrać wszystkie dane posta w jednym zapytaniu, a następnie pobrać odpowiednią postmetę w innym i połączyć meta z danymi postu w jednym zestawie wyników w PHP. Czy skończyłoby się to szybciej niż pojedyncze, coraz bardziej złożone zapytanie SQL, jeśli to w ogóle możliwe?
Zawsze myślę: „Daj bazę danych jak najwięcej pracy”. Nie jestem pewien w tej sprawie!
get_posts()
, toget_post_meta()
dla każdego z nich? @MannyFleurmond, trudno jest znaleźć twarde informacje na temat wbudowanego buforowania WP, ale AFAIK będzie buforować rzeczy na żądanie. Wezwanie do serwera, aby pobrać te dane, jest wywołaniem AJAX i nie sądzę, aby cokolwiek innego mogło przechwycić coś przed tym.Odpowiedzi:
Informacje meta po opublikowaniu są automatycznie buforowane w pamięci dla standardowego
WP_Query
(i głównego zapytania), chyba że wyraźnie powiesz mu, aby tego nie robił za pomocąupdate_post_meta_cache
parametru.Dlatego nie powinieneś pisać w tym celu własnych zapytań.
Jak działa meta-buforowanie w przypadku normalnych zapytań:
Jeśli
update_post_meta_cache
parametr parametruWP_Query
nie jest ustawiony na false, to po pobraniu postów z bazy danychupdate_post_caches()
zostanie wywołana funkcja, która z kolei wywołaupdate_postmeta_cache()
.Ta
update_postmeta_cache()
funkcja jest opakowaniemupdate_meta_cache()
i w zasadzie wywołuje prostySELECT
z wszystkimi pobranymi identyfikatorami postów. Spowoduje to, że pobierze całą postmetę dla wszystkich postów w zapytaniu i zapisze te dane w pamięci podręcznej obiektu (używającwp_cache_add()
).Kiedy robisz coś takiego
get_post_custom()
, najpierw sprawdza pamięć podręczną tego obiektu. Więc nie robi dodatkowych zapytań, aby uzyskać meta post w tym momencie. Jeśli dostałeś post wWP_Query
meta, to meta jest już w pamięci i od razu go pobiera.Korzyści tutaj są wielokrotnie większe niż tworzenie złożonych zapytań, ale największą zaletą jest użycie pamięci podręcznej obiektów. Jeśli korzystasz z trwałego rozwiązania do buforowania pamięci, takiego jak XCache lub memcached lub APC lub coś takiego, i masz wtyczkę, która może powiązać z nim pamięć podręczną obiektu (na przykład W3 Total Cache), wtedy pamięć podręczna całego obiektu jest przechowywana w szybkiej pamięci już. W takim przypadku, nie ma zerowe zapytania niezbędne do pobierania danych; jest już w pamięci. Trwałe buforowanie obiektów jest niesamowite pod wieloma względami.
Innymi słowy, twoje zapytanie prawdopodobnie ładuje się i ładuje wolniej niż przy użyciu właściwego zapytania i prostego trwałego rozwiązania pamięci. Użyj normalnego
WP_Query
. Zaoszczędź sobie wysiłku.Dodatkowo:
update_meta_cache()
jest inteligentny, BTW. Nie będzie pobierać meta informacji dla postów, które już mają swoje buforowane metadane. Zasadniczo nie otrzymuje tej samej meta dwa razy. Super wydajny.Dodatkowe dodatkowe: „Daj bazę danych jak najwięcej pracy.” ... Nie, to jest sieć. Obowiązują różne zasady. Ogólnie rzecz biorąc, zawsze chcesz poświęcić jak najmniej pracy bazie danych, jeśli jest to wykonalne. Bazy danych są powolne lub źle skonfigurowane (jeśli nie skonfigurowałeś go specjalnie, możesz postawić dobre pieniądze, że to prawda). Często są one udostępniane wielu witrynom i do pewnego stopnia przeciążone. Zwykle masz więcej serwerów internetowych niż baz danych. Ogólnie rzecz biorąc, chcesz po prostu pobrać potrzebne dane z bazy danych tak szybko i prosto, jak to możliwe, a następnie posortować je za pomocą kodu po stronie serwera WWW. Zasadniczo różne przypadki są różne.
źródło
Poleciłbym zapytanie przestawne. Na twoim przykładzie:
źródło
Natknąłem się na przypadek, w którym chcę również szybko pobrać wiele postów z powiązanymi z nimi meta informacjami. Muszę pobrać posty O (2000).
Wypróbowałem to, korzystając z sugestii Otto - uruchomiłem zapytanie WP_Query :: dla wszystkich postów, a następnie zapętliłem i uruchomiłem get_post_custom dla każdego postu. Zajęło to średnio około 3 sekund .
Następnie spróbowałem kwerendy przestawnej Ethana (chociaż nie lubiłem ręcznie pytać o każdy meta_key, który mnie interesował). Nadal musiałem przeglądać wszystkie pobrane posty, aby odserializować wartość meta_value. Zajęło to średnio około 1,3 sekundy .
Następnie spróbowałem użyć funkcji GROUP_CONCAT i znalazłem najlepszy wynik. Oto kod:
Zajęło to średnio 0,7 sekundy . To mniej więcej jedna czwarta czasu rozwiązania WP get_post_custom () i około połowy rozwiązania zapytań przestawnych.
Może to kogoś zainteresuje.
źródło
Znalazłem się w sytuacji, w której musiałem wykonać to zadanie, aby ostatecznie utworzyć dokument CSV, skończyłem z bezpośrednią współpracą z mysql, aby to zrobić. Mój kod dołącza do tabel pocztowych i meta, aby pobrać informacje o cenach woocommerce, wcześniej opublikowane rozwiązanie wymagało używania aliasów tabel w sql do poprawnego działania.
Ostrzegam jednak, woocommerce utworzyło ponad 300 000 wierszy w mojej tabeli meta, więc było bardzo duże, a zatem bardzo wolne.
źródło
BRAK WERSJI SQL:
Pobierz wszystkie posty i wszystkie ich meta wartości (meta) bez SQL:
Załóżmy, że masz listę identyfikatorów postów przechowywanych jako tablica identyfikatorów, coś w rodzaju
Teraz uzyskanie wszystkich postów i wszystkich meta w jednym zapytaniu nie jest możliwe bez użycia co najmniej odrobiny SQL, więc musimy wykonać 2 zapytania (nadal tylko 2):
1. Zdobądź wszystkie posty (używając WP_Query )
(Nie zapomnij zadzwonić,
wp_reset_postdata();
jeśli później wykonujesz „pętlę” ;))2. Zaktualizuj meta cache
Aby uzyskać metadane, użyj standardu,
get_post_meta()
który, jak wskazał @Otto:najpierw sprawdza pamięć podręczną :)
Uwaga: jeśli tak naprawdę nie potrzebujesz innych danych z postów (takich jak tytuł, treść, ...) , możesz zrobić tylko 2. :-)
źródło
używając rozwiązania trevor i modyfikując go do pracy z zagnieżdżonym SQL. To nie jest testowane.
źródło
Zetknąłem się również z problemem wielu pól meta wartości. Problem dotyczy samego WordPressa. Zajrzyj do wp-include / meta.php. Poszukaj tej linii:
Problem dotyczy instrukcji CAST. W zapytaniu o meta wartości zmienna $ meta_type jest ustawiona na CHAR. Nie znam szczegółów dotyczących tego, w jaki sposób CASTing wartości CHAR wpływa na szeregowany ciąg, ale aby to naprawić, możesz usunąć rzutowanie, aby SQL wyglądał następująco:
Teraz, mimo że to działa, masz do czynienia z wewnętrznymi elementami WordPress, więc inne rzeczy mogą się zepsuć i nie jest to trwała poprawka, zakładając, że musisz zaktualizować WordPress.
Naprawiłem to, kopiując kod SQL wygenerowany przez WordPress dla żądanego meta kwerendy, a następnie napisz trochę PHP, aby dodać dodatkowe instrukcje AND dla meta_wartości, których szukam, i użyj $ wpdb-> get_results ($ sql ) dla końcowego wyniku. Hacky, ale działa.
źródło
get_meta_sql
filtra następującego po tej linii byłoby oczywiście lepsze niż zhakowanie rdzenia kodu.