Cum să optimizezi un site WordPress pentru milioane de articole

25 oct. 2014, 19:53:21
Vizualizări: 23.8K
Voturi: 27

Lucrez la un site web pentru o companie care cel mai probabil va crea milioane de postări printr-un tip de postare personalizat. Acestea sunt rugăciuni, deci practic utilizatorul de pe frontend trimite doar o frază scurtă printr-un formular. Tot ce interesează compania este conținutul postării și data publicării. Site-ul nici măcar nu a fost lansat încă și deja au peste 120.000 de postări, așa că sunt foarte serios când spun milioane.

Deci, câteva întrebări despre optimizare:

  1. Să zicem că am o categorie 'featured' într-un tip de postare personalizat care are 500.000 de postări. Categoria featured are doar 500 de postări. Dacă creez o interogare pentru postările featured, interoghez toate cele 500.000 de postări sau doar cele 500 featured? Ce se întâmplă dacă vreau să afișez doar cele mai recente zece postări care sunt featured?
  2. Când salvez acest tip de postare personalizat în baza de date, există lucruri pe care le pot face pentru a reduce resursele serverului, mai ales că singurele lucruri necesare sunt conținutul postării și data?
  3. Ar trebui să folosesc un tip de postare personalizat? Îmi place în principiu pentru că este bine integrat în panoul de administrare WordPress, dar dacă există dezavantaje semnificative în ceea ce privește performanța, presupun că pot face altceva.

Nu am lucrat niciodată la un proiect de această amploare, așa că sunt puțin mai preocupat de performanță decât de obicei. Mulțumesc pentru orice ajutor!

2
Comentarii

Este important să menții numărul de interogări la baza de date la minimum în funcțiile tale WordPress și să apelezi scripturile în mod corespunzător, dar o mare parte din optimizare are legătură cu modul în care serverul este configurat și setat. Pentru asta, caută pe rețeaua Server Fault. http://serverfault.com/search?q=optimize+wordpress

iyrin iyrin
26 oct. 2014 05:24:12

@RyanLoremIpsum - mulțumesc pentru comentariu, dar speram să obțin răspunsuri la întrebările mele specifice. Majoritatea informațiilor găsite acolo se referă la server în sine, nu la modul în care funcționează WordPress și cum să-l optimizezi din perspectiva codului

Jeremiah Prummer Jeremiah Prummer
28 oct. 2014 02:20:55
Toate răspunsurile la întrebare 3
3
35

1. Setează interogarea înainte ca WP_Query să fie executată

Acesta pare a fi cel mai important lucru de reținut atunci când încerci să reduci la minimum interogările la baza de date, deoarece singura oportunitate de a modifica interogarea este, bineînțeles, înainte ca aceasta să fie executată în baza de date SQL.

Interogări normale
Pentru o interogare normală, WordPress folosește funcția wp(), care la rândul ei apelează $wp->main( $query_vars ). Variabilele "is_" din etichetele condiționale sunt setate înainte de a fi transmise către WP_Query->get_posts(), care le convertește într-o interogare MySQL și le stochează în obiectul $wp_query. Este posibil să filtrezi interogarea înainte ca aceasta să fie efectiv executată în baza de date SQL.

Acțiunea pre_get_posts se atașează acestui proces, permițându-ți să modifici interogarea înainte ca aceasta să fie transmisă către WP_Query->get_posts().

De exemplu, dacă vrei să filtrezi interogarea pentru postările din categoria "featured", ai folosi add_action( 'pre_get_posts', 'your_function_name' ); și ai include eticheta condițională in_category în interiorul funcției your_function_name.

function your_function_name( $query ) {
    if ( $query->in_category( 'featured' ) && $query->is_main_query() ) {
        // Înlocuiește 123 cu ID-ul categoriei featured.
        $query->set( 'cat', '123' );
    }
}
add_action( 'pre_get_posts', 'your_function_name' );

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

Solicitări de pagină
În cazul șabloanelor de pagină, cum ar fi pagina de arhivă pentru categoria "featured", etichetele condiționale nu vor funcționa din filtrul pre_get_posts. De exemplu, nu poți folosi is_category pentru a verifica pagina de arhivă deoarece WP_Query nu a fost încă executat.

În schimb, ar trebui să modifici interogarea principală pentru solicitările de pagină cu un new WP_Query, care ar arăta cam așa: $query = new WP_Query( 'cat=123' );. Aceasta execută interogarea cu argumentul potrivit setat de la început.

Vezi Class Reference/WP Query « WordPress Codex

2. Salvarea în baza de date

Poți folosi filtrul wp_insert_post_data asigurându-te că doar $data relevantă pentru tipul tău personalizat de post este returnată către wp_insert_post. Asigură-te că incluzi o declarație condițională pentru a verifica tipul tău personalizat de post.
Plugin API/Filter Reference/wp insert post data « WordPress Codex

Acest hook este apelat de funcția wp_insert_post, care este apelată de wp_update_post atunci când actualizezi tipul tău personalizat de post, de obicei prin salvarea unui draft sau publicarea postului.

Totuși, va trebui să faci benchmarking singur, deoarece nu pot afirma personal semnificația optimizării prin reducerea datelor care sunt actualizate în baza de date.

3. Tipurile personalizate de post afectează performanța?

Din experiența mea, tipurile personalizate de post sunt un instrument puternic pentru gestionarea conținutului. Nu cunosc alt mod de a gestiona postările în toate modurile pe care le permite într-o manieră care să consume mai puține resurse. Personal, m-aș concentra pe găsirea de modalități de a reduce numărul de interogări efectuate oriunde este posibil.

În trecut, exista o problemă de performanță legată de structura permalink-ului, care făcea ca performanța să scadă atunci când începea cu text în loc de un număr.3 Aceasta a fost problematică în special pentru site-urile care găzduiau un număr mare de pagini, dar a fost rezolvată începând cu versiunea 3.3 a WordPress.

Menționez permalink-urile aici deoarece slug-ul este de obicei prima parte a structurii permalink-ului, care poate sau nu să fi afectat performanța înainte de versiunea 3.3. În afară de aceasta, nu cunosc alte probleme de performanță care să apară din utilizarea tipurilor personalizate de post.

Alte opțiuni de performanță

Transiente
Aceasta nu este o înlocuire pentru menținerea interogărilor la minimum în codul tău, dar poți folosi set_transient pentru a stoca interogările pentru o anumită perioadă, astfel încât să nu fie necesare noi interogări. Iată exemplul folosit în postul lui Dave Clements. De asemenea, reține că el recomandă adăugarea unei acțiuni save_post pentru a șterge transienta ori de câte ori un anumit tip de post este actualizat.

<?php // INTEROGAREA IN THE SPOTLIGHT
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() ) { // ASCUNDE SECȚIUNEA DACĂ NU EXISTĂ NICIUN FEATURE ITS CURENT ?>
    // BUCLA AICI: NU ESTE IMPORTANTĂ PENTRU EXEMPLU
<?php } ?>

Mai multă optimizare a interogărilor
Thomas Griffin are câteva sfaturi bune în tutorialul său Optimize WordPress Queries. Iată o listă scurtă cu sugestiile sale:

  • Setează 'cache_results' => false în interogările unice dacă serverul tău nu utilizează caching persistent, cum ar fi Memcached. Interogările unice sunt descrise ca "interogări care sunt folosite pentru a afișa cantități mici de date. Poate fi vorba doar de afișarea titlurilor postărilor legate de postul curent, sau poate dorești să afișezi un dropdown cu postări pentru a selecta o anumită opțiune."

    Exemplul său: $query = get_posts( array( 'posts_per_page' => 1, 'cache_results' => false ) );

  • Setează 'no_found_rows' => true acolo unde nu este necesară paginarea. Aceasta va "ocoli numărarea rezultatelor în MySQL pentru a vedea dacă avem nevoie de paginare sau nu."

    Exemplul său: $query = new WP_Query( array( 'posts_per_page' => 1, 'no_found_rows' => true ) );

  • Interoghează doar pentru ID-uri de post dacă acesta este tot ce ai nevoie 'fields' => 'ids' în get_posts. Aceasta ar trebui să reducă semnificativ cantitatea de date returnate, care este destul de mare per post dacă te uiți la Database Description « WordPress Codex.

    Exemplul său: $query = get_posts( array( 'posts_per_page' => 1, 'fields' => 'ids' ) );

În plus față de ultimul sfat, același raționament poate fi aplicat atunci când ai nevoie doar de unul sau câteva câmpuri de post folosind get_post_field.

A avea o înțelegere solidă despre cum funcționează interogarea este esențial. Cu cât poți fi mai specific cu interogările tale, cu atât mai puțină muncă vei cere de la baza ta de date SQL. Aceasta înseamnă că există un număr vast de posibilități pentru gestionarea interogărilor la baza de date. Fii atent cu interogările personalizate în ceea ce privește locul în care rulează (este o pagină de administrare?), folosește sanitizare corespunzătoare în interogările directe și încearcă să utilizezi funcții native WordPress acolo unde îți permite să obții aceeași performanță.

28 oct. 2014 12:37:44
Comentarii

Răspuns excelent și extrem de util, mulțumesc!

Jeremiah Prummer Jeremiah Prummer
28 oct. 2014 16:50:32

Tema este construită complet personalizată, așa că efectiv interogăm doar elementele absolut esențiale. Totuși, acestea sunt extrem de utile. Având în vedere acest lucru, voi reveni și voi face niște modificări la interogările mele. ;)

Jeremiah Prummer Jeremiah Prummer
28 oct. 2014 16:52:27

Aș adăuga că ar trebui să evitați interogările meta oriunde este posibil. Cu siguranță nu rulați o interogare împotriva a două câmpuri meta simultan. Acest lucru duce la interogări duble și triple care devin rapid un coșmar de performanță. Tipurile de postări personalizate pot ajuta adesea în acest sens.

Juniper Jones Juniper Jones
9 feb. 2016 17:38:13
2

De asemenea, adaug:

    'no_found_rows'          => true,
    'update_post_term_cache' => false,
    'update_post_meta_cache' => false,
    'cache_results'          => false
  • no_found_rows (boolean) - setează true când nu ai nevoie de paginare și nici de numărul total de articole găsite.
  • cache_results (boolean) - Cache pentru informațiile despre articol.
  • update_post_meta_cache (boolean) - Cache pentru meta informațiile articolului.
  • update_post_term_cache (boolean) - Cache pentru informațiile de termeni ai articolului.

Folosind acești parametri și trecând valori FALSE, putem face interogarea mai rapidă prin oprirea unor interogări suplimentare la baza de date.

Notă: Nu ar trebui să folosim întotdeauna acești parametri, deoarece adăugarea în cache este cea mai bună practică. Totuși, aceștia pot fi utili în anumite circumstanțe specifice și ar trebui luați în considerare doar dacă știi exact ce faci.

Vizitează: https://drujoopress.wordpress.com/2013/06/27/how-to-optimize-wordpress-query-to-get-results-faster/#more-184

3 mar. 2018 11:04:11
Comentarii

Te rog să [editezi] răspunsul tău și să adaugi o explicație: de ce ar putea rezolva problema?

fuxia fuxia
3 mar. 2018 14:55:17

Nu pot adăuga comentariul meu la acest răspuns: https://wordpress.stackexchange.com/a/166699/57674

rigosan rigosan
4 mar. 2018 13:19:17
0

Ca toate întrebările despre optimizarea prematură, aceasta nu poate fi răspunsă cu adevărat fără a cunoaște modelele exacte de utilizare, care de multe ori sunt descoperite doar când mergi live.

În general, conform specificațiilor MYSQL, nu ar trebui să existe nicio problemă cu cantitatea de date. Desigur, căutarea datelor chiar și cu cele mai bune algoritme va fi mai lentă decât cu tabele mult mai mici, dar soluția pentru aceasta este simplă - un procesor mai puternic.

Puteți dori să optimizați modul în care sunt stocate metadatele (de exemplu, să nu stocați date legate de ping), dar acest gen de lucru depinde de exact ce faceți, iar în final s-ar putea să aveți nevoie totuși de un procesor mai puternic, așa că s-ar putea să nu merite efortul.

28 oct. 2014 13:46:57