Jak zoptymalizować witrynę WP pod kątem milionów postów

19

Pracuję nad witryną dla firmy, która najprawdopodobniej będzie tworzyć miliony postów za pomocą niestandardowego typu postów. Są to modlitwy, więc w zasadzie użytkownik frontonu po prostu przesyła krótką frazę za pomocą formularza. Wszystkim, którym zależy na firmie, jest treść postu i data publikacji. Witryna jeszcze się nie uruchomiła i ma już ponad 120 000 postów, więc mówię, że miliony.

Kilka pytań dotyczących optymalizacji:

  1. Załóżmy, że mam kategorię „polecaną” w niestandardowym typie postów, która ma 500 000 postów. Wybrana kategoria ma tylko 500 postów. Jeśli utworzę zapytanie o polecane posty, czy sprawdzę całe 500 000 postów, czy tylko 500 polecanych? Co się stanie, jeśli chcę wyświetlić tylko dziesięć ostatnio publikowanych postów?
  2. Czy podczas zapisywania tego niestandardowego typu postu w bazie danych mogę coś zrobić, aby zmniejszyć zasoby serwera, zwłaszcza że jedyne, czego naprawdę potrzebuję, to treść postu i data?
  3. Czy powinienem nawet używać niestandardowego typu postu? Zasadniczo mi się podoba, ponieważ jest dobrze zintegrowany z administratorem WordPress, ale jeśli występują znaczne wady wydajności, to przypuszczam, że mogę zrobić coś innego.

Nigdy nie pracowałem nad projektem na taką skalę, więc bardziej niż zwykle martwię się wydajnością. Dzięki za wszelką pomoc!

Jeremiasz Prummer
źródło
Ważne jest, aby zapytania bazy danych były ograniczone do minimum w funkcjach WordPress i odpowiednio wywoływały skrypty, ale duża część optymalizacji ma związek z konfiguracją i konfiguracją serwera. W tym celu wyszukaj sieć Usterka serwera. serverfault.com/search?q=optimize+wordpress
iyrin
@RyanLoremIpsum - dziękuję za komentarz, ale liczyłem na odpowiedzi na moje szczegółowe pytania. Większość tego, co tam znalazłem, dotyczy samego serwera, a nie tego, jak działa WordPress i jak go zoptymalizować z perspektywy kodu
Jeremiah Prummer,

Odpowiedzi:

26

1. Ustaw zapytanie przed uruchomieniem WP_Query

Wydaje się, że jest to najważniejsza rzecz, o której należy pamiętać, próbując ograniczyć zapytania do bazy danych do minimum, ponieważ jedyną możliwością zmiany zapytania jest oczywiście jego uruchomienie w bazie danych SQL.

Normalne zapytania
W przypadku normalnego zapytania WordPress korzysta z wp()funkcji, która z kolei wywołuje $wp->main( $query_vars ). Zmienne „is_” z tagów warunkowych są ustawiane przed przekazaniem ich do WP_Query->get_posts(), co konwertuje je na zapytanie do bazy danych MySQL i ostatecznie przechowuje je w obiekcie $ wp_query. Możliwe jest odfiltrowanie zapytania, zanim zostanie ono faktycznie uruchomione w bazie danych SQL .

pre_get_postsDziałanie haki do tego procesu, co pozwala zmienić zapytanie, zanim zostanie przekazany do WP_Query->get_posts().

Na przykład, jeśli chcesz odfiltrować zapytanie pod kątem postów w kategorii „polecany”, użyj add_action( 'pre_get_posts', 'your_function_name' );i umieść w nim in_categorytag warunkowy your_function_name.

function your_function_name( $query ) {
    if ( $query->in_category( 'featured' ) && $query->is_main_query() ) {
        // Replace 123 with the category ID of the featured category.
        $query->set( 'cat', '123' );
    }
}
add_action( 'pre_get_posts', 'your_function_name' );

Zobacz Plugin API / Action Reference / pre get posts «WordPress Codex

Żądania strony
Podobnie jak w przypadku szablonów stron, takich jak strona archiwum dla kategorii „polecane”, tagi warunkowe nie będą działać z pre_get_postsfiltra. Na przykład nie można użyć is_categorydo sprawdzenia strony archiwum, ponieważ WP_Query nie został uruchomiony.

Zamiast tego musiałbyś zmienić główne zapytanie dla żądań strony, new WP_Queryktóre wyglądałoby mniej więcej tak $query = new WP_Query( 'cat=123' );. Spowoduje to uruchomienie zapytania z odpowiednim zestawem argumentów od początku.

Patrz Odwołanie do klasy / Zapytanie WP «Kodeks WordPress

2. Zapisywanie w bazie danych

Możesz użyć filtru, wp_insert_post_dataaby upewnić się, że zwracane są tylko dane $ związane z niestandardowym typem postu wp_insert_post. Pamiętaj o dołączeniu instrukcji warunkowej, aby sprawdzić niestandardowy typ postu.
Plugin API / Filter Reference / wp insert post data «WordPress Codex

Ten hak jest wywoływany przez wp_insert_postfunkcję, która jest wywoływana przez wp_update_post podczas aktualizacji niestandardowego typu postu, zwykle przez zapisanie wersji roboczej lub opublikowanie posta.

Trzeba będzie to jednak przeprowadzić samodzielnie, ponieważ nie mogę osobiście mówić o znaczeniu optymalizacji, jaką jest ograniczenie danych aktualizowanych w bazie danych.

3. Czy niestandardowe typy wpisów wpływają na wydajność?

Z mojego doświadczenia wynika, że ​​niestandardowe typy postów są potężnym narzędziem do zarządzania zawartością. Nie znam żadnego innego sposobu zarządzania postami na wszystkie sposoby, na które pozwala w sposób, który zużyłby mniej zasobów. Osobiście skupiłbym się na znalezieniu sposobów na zmniejszenie liczby zapytań w miarę możliwości.

Kiedyś występował problem z wydajnością związany ze strukturą permalink, która powodowała, że ​​trafiał, gdy zaczyna się od tekstu zamiast liczby. 3 Było to szczególnie kłopotliwe dla witryn obsługujących dużą liczbę stron, ale zostało rozwiązane od wersji WordPress 3.3.

Przywołuję tutaj tylko linki bezpośrednie, ponieważ ślimak jest zwykle pierwszą częścią struktury łącza bezpośredniego, która mogła mieć wpływ na wydajność przed wersją 3.3. Poza tym nie jestem świadomy żadnych problemów z wydajnością, które wynikają z używania niestandardowych typów postów.

Inne opcje wydajności

Przejściowe
Nie zastępuje to ograniczania zapytań do minimum w kodzie, ale można użyć set_transient do przechowywania zapytań przez pewien czas, aby nowe zapytania nie były konieczne. Oto przykład użyty w poście Dave'a Clementsa . Zauważ też, że zaleca dodanie save_postakcji usuwającej stan przejściowy przy każdej aktualizacji danego typu postu.

<?php // IN THE SPOTLIGHT QUERY
if( false === ( $its_query = get_transient( 'its_query' ) ) ) {
    $pttimestamp = time() + get_option('gmt_offset') * 60*60;
    $its_query = new WP_Query( array(
        'post_type' => 'spotlight',
        'posts_per_page' => 1,
            'post__not_in' => $do_not_duplicate,
        'meta_query' => array(
            array(
                'key' => '_hpc_spotlight_end_time',
                'value' => $pttimestamp,
                'compare' => '>'
            )
        )
    ) );
    set_transient( 'its_query', $its_query, 60*60*4 );
}
if( have_posts() ) { // HIDE SECTION IF NO CURRENT ITS FEATURE ?>
    // LOOP GOES HERE: NOT IMPORTANT TO EXAMPLE
<?php } ?>

Więcej optymalizacji zapytań
Thomas Griffin ma kilka dobrych wskazówek w swoim samouczku dotyczącym optymalizacji zapytań WordPress . Oto krótka lista jego sugestii:

  • Ustaw 'cache_results' => falsew zapytaniach jednorazowych, jeśli serwer nie używa trwałego buforowania, takiego jak Memcached. Zapytania jednorazowe są opisywane jako „zapytania służące do wyświetlania niewielkich ilości danych. Może być tak, że chcesz wyświetlać tylko powiązane tytuły postów związane z bieżącym postem lub wyświetlać listę postów do wyboru szczególne ustawienie opcji ”.

    Jego przykład: $query = get_posts( array( 'posts_per_page' => 1, 'cache_results' => false ) );

  • Ustaw, 'no_found_rows' => truegdzie paginacja nie jest potrzebna. Spowoduje to „pominięcie MySQL liczenia wyników, aby zobaczyć, czy potrzebujemy paginacji, czy nie”.

    Jego przykład: $query = new WP_Query( array( 'posts_per_page' => 1, 'no_found_rows' => true ) );

  • Zapytanie pocztowych identyfikatorów tylko wtedy, gdy jest to wszystko, czego potrzebujesz 'fields' => 'ids' w get_posts. Powinno to znacznie zmniejszyć ilość zwracanych danych, co stanowi całkiem sporo na post, jeśli spojrzysz na Opis bazy danych «WordPress Codex

    Jego przykład: $query = get_posts( array( 'posts_per_page' => 1, 'fields' => 'ids' ) );

Oprócz tej ostatniej wskazówki można zastosować to samo rozumowanie, gdy potrzebujesz tylko jednego lub kilku pól postów, używając get_post_field .

Niezbędne jest dokładne zrozumienie działania zapytania. Im bardziej szczegółowe są zapytania, tym mniej pracy będzie wymagać od bazy danych SQL. Oznacza to, że istnieje wiele możliwości zarządzania zapytaniami do baz danych. Zachowaj ostrożność przy niestandardowych zapytaniach, o ile są one uruchamiane (czy jest to strona administratora?), Używaj właściwej dezynfekcji w bezpośrednich zapytaniach i próbuj używać natywnych funkcji WordPress, które pozwalają osiągnąć taką samą wydajność.

iyrin
źródło
2
Doskonała i niezwykle pomocna odpowiedź, dziękuję!
Jeremiah Prummer
Motyw jest w pełni zbudowany na zamówienie, więc dosłownie pytamy tylko o absolutnie niezbędne elementy. Są to jednak bardzo pomocne. Biorąc to pod uwagę, zamierzam wrócić i wprowadzić zmiany w moich zapytaniach. ;)
Jeremiah Prummer
1
Dodam, że należy unikać meta-zapytań, gdzie tylko jest to możliwe. Z pewnością nie uruchamiaj zapytania jednocześnie dla dwóch pól meta. Powoduje to podwójne i potrójne zapytania, które szybko stają się nigtmare wydajności. Niestandardowe typy postów często mogą w tym pomóc.
Charles Jaimet,
3

Dodaję również:

    'no_found_rows'          => true,
    'update_post_term_cache' => false,
    'update_post_meta_cache' => false,
    'cache_results'          => false
  • no_found_rows (boolean) - spraw, aby było to prawdą, gdy nie potrzebujesz podziału na strony i nie potrzebujesz liczenia całkowitej liczby znalezionych postów.
  • cache_results (boolean) - Pamięć podręczna informacji.
  • update_post_meta_cache (boolean) - Post cache informacji o meta.
  • update_post_term_cache (boolean) - Pamięć podręczna informacji o terminie.

Używając tych parametrów i przekazując wartości jako FAŁSZ, możemy przyspieszyć zapytanie, zatrzymując wykonywanie dodatkowych zapytań do bazy danych.

Uwaga: nie powinniśmy używać tych parametrów zawsze, ponieważ poprawne jest dodawanie elementów do pamięci podręcznej, jednak mogą one być przydatne w określonych okolicznościach i powinieneś rozważyć ich użycie, gdy wiesz, co robisz.

Proszę odwiedzić: https://drujoopress.wordpress.com/2013/06/27/how-to-optimize-wordpress-query-to-get-results-faster/#more-184

rigosan
źródło
1
Proszę edytować swoje odpowiedzi i dodać wyjaśnienie: dlaczego to może rozwiązać problem?
fuxia
Nie mogę dodać komentarza do tej odpowiedzi: wordpress.stackexchange.com/a/166699/57674
rigosan
1

Jak na wszystkie pytania związane z przedwczesną optymalizacją, na to pytanie nie można odpowiedzieć bez znajomości dokładnych wzorców użytkowania, które zbyt wiele razy są odkrywane dopiero po uruchomieniu.

Ogólnie rzecz biorąc, według specyfikacji MYSQL nie powinno być problemu z ilością danych. Oczywiście wyszukiwanie danych nawet przy użyciu najlepszych algorytmów będzie wolniejsze niż przy znacznie mniejszych tabelach, ale rozwiązaniem tego jest prosty, mocniejszy procesor.

Możesz zoptymalizować sposób przechowywania metadanych (na przykład, aby nie przechowywać danych powiązanych z pingiem), ale tego rodzaju rzeczy zależą od tego, co dokładnie robisz, a na koniec nadal możesz potrzebować mocniejszego procesora, więc może nie być warto .

Mark Kaplun
źródło