Cómo optimizar el sitio de WP para millones de publicaciones

19

Estoy trabajando en un sitio web para una empresa que probablemente creará millones de publicaciones a través de un tipo de publicación personalizado. Son oraciones, por lo que, básicamente, el usuario en el front end simplemente envía una frase corta a través de un formulario. Lo único que le importa a la empresa es el contenido de la publicación y la fecha de publicación. El sitio aún no se ha lanzado y ya tienen más de 120,000 publicaciones, así que estoy hablando en serio cuando digo millones.

Entonces, un par de preguntas de optimización:

  1. Digamos que tengo una categoría 'destacada' en un tipo de publicación personalizada que tiene 500,000 publicaciones. La categoría destacada solo tiene 500 publicaciones. Si creo una consulta para las publicaciones destacadas, ¿estoy consultando las 500,000 publicaciones completas o solo las 500 destacadas? ¿Qué sucede si solo quiero mostrar las diez publicaciones más recientes que aparecen?
  2. Al guardar este tipo de publicación personalizada en la base de datos, ¿hay algo que pueda hacer para reducir los recursos del servidor, especialmente porque lo único que realmente se necesita es el contenido de la publicación y la fecha?
  3. ¿Debería incluso usar un tipo de publicación personalizado? En principio, me gusta porque está bien integrado en el administrador de WordPress, pero si hay desventajas significativas en el rendimiento, entonces supongo que puedo hacer algo diferente.

Nunca he trabajado en un proyecto a esta escala, así que estoy un poco más preocupado por el rendimiento de lo habitual. ¡Gracias por cualquier ayuda!

Jeremiah Prummer
fuente
Es importante mantener las consultas de la base de datos al mínimo en sus funciones de WordPress y en los scripts de llamadas de manera adecuada, pero una gran parte de la optimización tiene que ver con la configuración y configuración del servidor. Para eso, busque en la red de Falla del servidor. serverfault.com/search?q=optimize+wordpress
iyrin
@RyanLoremIpsum: gracias por el comentario, pero esperaba respuestas a mis preguntas específicas. La mayor parte de lo que encontré allí trata sobre el servidor en sí, no sobre cómo funciona WordPress y cómo optimizarlo desde una perspectiva de código
Jeremiah Prummer,

Respuestas:

26

1. Establezca la consulta antes de ejecutar WP_Query

Esto parece ser lo más importante a tener en cuenta al tratar de mantener las consultas a la base de datos al mínimo, ya que la única oportunidad de alterar la consulta es, por supuesto, antes de que se ejecute en la base de datos SQL.

Consultas normales
Para una consulta normal, WordPress usa la wp()función, que a su vez llama $wp->main( $query_vars ). Las "variables is_" de las etiquetas condicionales se establecen antes de pasarlas WP_Query->get_posts(), lo que lo convierte en una consulta de base de datos MySQL y finalmente las almacena en el objeto $ wp_query. Es posible filtrar la consulta antes de que realmente se ejecute en la base de datos SQL .

La pre_get_postsacción se engancha en este proceso, permitiéndole cambiar la consulta antes de pasarla WP_Query->get_posts().

Por ejemplo, si desea filtrar la consulta para publicaciones en la categoría "destacado", usaría add_action( 'pre_get_posts', 'your_function_name' );e incluiría la in_categoryetiqueta condicional dentro 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' );

Ver API de complementos / Referencia de acciones / pre get posts «WordPress Codex

Solicitudes
de página En cuanto a las plantillas de página, como la página de archivo para la categoría "destacado", las etiquetas condicionales no funcionarán desde el pre_get_postsfiltro. Por ejemplo, no puede usar is_categorypara verificar la página de archivo porque WP_Query no se ha ejecutado.

En cambio, tendría que alterar la consulta principal para solicitudes de página con una new WP_Queryque se parecería a algo así $query = new WP_Query( 'cat=123' );. Esto ejecuta la consulta con el argumento apropiado establecido desde el principio.

Ver referencia de clase / consulta WP «Codex de WordPress

2. Guardar en la base de datos

Puede usar el filtro para wp_insert_post_dataasegurarse de que solo se devuelvan los datos $ relevantes para su tipo de publicación personalizada wp_insert_post. Asegúrese de incluir una declaración condicional para verificar su tipo de publicación personalizada.
Complemento API / Referencia de filtro / wp insertar datos de publicación «WordPress Codex

La wp_insert_postfunción llama a este enlace , que wp_update_post llama cuando actualiza su tipo de publicación personalizada, generalmente guardando un borrador o publicando la publicación.

Sin embargo, tendrá que compararlo usted mismo, ya que no puedo hablar personalmente sobre la importancia de la optimización de reducir los datos que se actualizan en la base de datos.

3. ¿Los tipos de publicaciones personalizadas afectan el rendimiento?

En mi experiencia, los tipos de publicaciones personalizadas son una herramienta poderosa para administrar el contenido. No conozco ninguna otra forma de administrar las publicaciones de todas las formas que permite de una manera que usaría menos recursos. Me centraría personalmente en encontrar formas de reducir la cantidad de consultas realizadas siempre que sea posible.

Solía ​​haber un problema de rendimiento relacionado con la estructura de enlaces permanentes que causaba un impacto cuando comienza con texto en lugar de un número. 3 Esto fue particularmente problemático para los sitios que alojan una gran cantidad de páginas, pero se ha resuelto desde la versión 3.3 de WordPress.

Solo menciono los enlaces permanentes aquí porque la babosa suele ser la primera parte de la estructura de enlaces permanentes que puede haber afectado o no el rendimiento antes de la versión 3.3. Aparte de eso, no conozco ningún problema de rendimiento que surja del uso de tipos de publicaciones personalizadas.

Otras opciones de rendimiento

Transitorios
Esto no es un reemplazo para mantener las consultas al mínimo en su código, pero puede usar set_transient para almacenar las consultas durante un tiempo para que no sean necesarias nuevas consultas. Aquí está el ejemplo utilizado en la publicación de Dave Clements . Además, tenga en cuenta que recomienda agregar una save_postacción para eliminar el transitorio cada vez que se actualiza un tipo de publicación determinado.

<?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 } ?>

Más optimización de consultas
Thomas Griffin tiene algunos buenos consejos en su tutorial Optimizar consultas de WordPress . Aquí hay una breve lista de sus sugerencias:

  • Se establece 'cache_results' => falseen consultas únicas si su servidor no está usando el almacenamiento en caché persistente, como Memcached. Las consultas únicas se describen como "consultas que se utilizan para mostrar pequeñas cantidades de datos. Puede ser que solo desee mostrar títulos de publicaciones vinculadas relacionadas con la publicación actual, o puede que desee mostrar un menú desplegable de publicaciones para seleccionar una configuración de opción particular ".

    Su ejemplo: $query = get_posts( array( 'posts_per_page' => 1, 'cache_results' => false ) );

  • Establecer 'no_found_rows' => truedonde no se necesita paginación. Esto "omitirá MySQL contando los resultados para ver si necesitamos paginación o no".

    Su ejemplo: $query = new WP_Query( array( 'posts_per_page' => 1, 'no_found_rows' => true ) );

  • Consulta para los ID de colocar sólo si esto es todo lo que necesita 'fields' => 'ids' en get_posts. Esto debería reducir significativamente la cantidad de datos que se devuelven, que es bastante por publicación si nos fijamos en la Descripción de la base de datos «WordPress Codex

    Su ejemplo: $query = get_posts( array( 'posts_per_page' => 1, 'fields' => 'ids' ) );

Además de ese último consejo, se puede aplicar el mismo razonamiento cuando solo necesita uno o unos pocos campos de publicación utilizando get_post_field .

Tener una comprensión sólida de cómo funciona la consulta es esencial. Cuanto más específico sea con sus consultas, menos trabajo demandará de su base de datos SQL. Esto significa que hay una gran cantidad de posibilidades para administrar consultas de bases de datos. Tenga cuidado con las consultas personalizadas en cuanto a dónde se ejecutan (¿es una página de administración?), Use la desinfección adecuada en consultas directas e intente usar las funciones nativas de WordPress donde le permite lograr el mismo rendimiento.

iyrin
fuente
2
Excelente y extremadamente útil respuesta, ¡gracias!
Jeremiah Prummer
El tema está completamente personalizado, por lo que literalmente solo consultamos los elementos absolutamente esenciales. Sin embargo, estos son extremadamente útiles. Teniendo esto en cuenta, volveré y haré algunos cambios en mis consultas. ;)
Jeremiah Prummer
1
Me gustaría agregar que debes evitar las meta consultas siempre que sea posible. Ciertamente, no ejecute una consulta en dos metacampos simultáneamente. Esto da como resultado consultas dobles y triples que rápidamente se convierten en una pesadilla de rendimiento. Los tipos de publicaciones personalizadas a menudo pueden ayudar con esto.
Charles Jaimet
3

También agrego:

    'no_found_rows'          => true,
    'update_post_term_cache' => false,
    'update_post_meta_cache' => false,
    'cache_results'          => false
  • no_found_rows (boolean): hazlo realidad cuando no necesites paginación y no necesites el conteo para el número total de publicaciones encontradas.
  • cache_results (boolean) - Publicar caché de información.
  • update_post_meta_cache (boolean): publica caché de metainformación.
  • update_post_term_cache (boolean): caché de información de término de publicación.

Al usar estos parámetros y pasar valores como FALSO, podemos hacer que la consulta sea más rápida al detener algunas consultas adicionales de la base de datos que se ejecutan.

Nota: No debemos usar estos parámetros siempre, ya que agregar cosas al caché es lo correcto, sin embargo, esto puede ser útil en circunstancias específicas y debe considerar usarlo cuando sepa lo que está haciendo.

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

rigosan
fuente
1
Por favor, editar su respuesta , y añadir una explicación: ¿por qué podría que resolver el problema?
fuxia
No puedo agregar mi comentario sobre esta respuesta: wordpress.stackexchange.com/a/166699/57674
rigosan
1

Como todas las preguntas de tipo de optimización prematura, esta realmente no se puede responder sin conocer los patrones de uso exactos que muchas veces se descubren solo cuando se activa.

En general, según las especificaciones MYSQL no debería haber ningún problema con la cantidad de datos. Por supuesto, la búsqueda de datos incluso con los mejores algoritmos será más lenta que con tablas mucho más pequeñas, pero la solución es una CPU simple y más fuerte.

Es posible que desee optimizar la forma en que se almacenan los metadatos (por ejemplo, no almacenar datos relacionados con ping), pero este tipo de cosas depende de lo que haga exactamente y, al final, es posible que aún necesite una CPU más fuerte, por lo que podría no valer la pena. .

Mark Kaplun
fuente