WordPress Ajax Consulta personalizada - Carga alta de CPU -- javascript campo con php campo con jquery campo con mysql campo con wordpress camp codereview Relacionados El problema

Wordpress Ajax Custom Query - High CPU LOAD


3
vote

problema

Español

Estoy desarrollando un tema de WP Community completamente AJAX que viene con muchas consultas personalizadas.

Todo está bien, no hay ningún error, pero recientemente, pero tenía algunos clientes que tienen una gran base de datos y mi tema comenzó a matar a la CPU. Me pregunto cómo puedo hacerlo correr más rápido.

¿Qué está haciendo este código?

Este código está tratando de obtener publicaciones que solo contengan comentarios "comentarios" comentarios (comment_type = "comentario") y los aprobados.

Información de la base de datos: mysql - mariadb

Nombre de la tabla que estoy tratando de obtener resultados - wp_comments

cuántos datos tienen la tabla: 380.000 (380k) Comentarios

Tiempo de salida crudo de la consulta en phpmyadmin (W / O PHP) - 0.23 segundos

Time para obtener estos datos en la parte delantera - 0.85-90 segundos

el código JS que llama a la función

      function lfload(page) {   $("#sol-load").css("opacity","0.75");   document.cookie = "lf= popular;  expires = Fri, 31 Dec 9999 23:59:59 GMT; path=/";   document.cookie = "popular_page = " + page + ";  expires = Fri, 31 Dec 9999 23:59:59 GMT; path=/";   var xhr = new XMLHttpRequest();   xhr.open("POST", bilgi.tema_url + '/admin-ajax.php', true);   xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");   xhr.onreadystatechange = function() {     if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {       document.getElementById("sol-load").innerHTML = this.response;       $("#sol-load").css("opacity","1");   }   }   xhr.send("action=popular_ajax"); }   

Código PHP para obtener datos

  package net.coderodde.graph.support;  import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import net.coderodde.graph.AbstractGraphNode;  /**  * This class implements a directed graph node.  *   * @author Rodion "rodde" Efremov  * @version 1.6 (Oct 11, 2015)  */ public class DirectedGraphNode extends AbstractGraphNode<DirectedGraphNode> {      private final Set<DirectedGraphNode> children = new LinkedHashSet<>();     private final Set<DirectedGraphNode> parents  = new LinkedHashSet<>();      private final Set<DirectedGraphNode> childrenWrapper =              Collections.<DirectedGraphNode>unmodifiableSet(children);      private final Set<DirectedGraphNode> parentsWrapper =              Collections.<DirectedGraphNode>unmodifiableSet(parents);      /**      * Constructs a new directed graph node with given name.      *       * @param name the name of the node.      */     public DirectedGraphNode(String name) {         super(name);     }      @Override     public void addChild(DirectedGraphNode child) {         checkNodeBelongsToGraph();          if (child == null) {             return;         }          children.add(child);         child.parents.add(this);         addEdges(1);     }      @Override     public boolean hasChild(DirectedGraphNode node) {         return children.contains(node);     }      @Override     public boolean hasParent(DirectedGraphNode node) {         return parents.contains(node);     }      @Override     public void removeChild(DirectedGraphNode node) {         if (node == null) {             return;         }          if (node.getOwnerGraph() != this.getOwnerGraph()) {             return;         }          if (!children.contains(node)) {             return;         }          children.remove(node);         node.parents.remove(this);         addEdges(-1);     }      @Override     public Set<DirectedGraphNode> children() {         return childrenWrapper;     }      @Override     public Set<DirectedGraphNode> parents() {         return parentsWrapper;     }      @Override     public void clear() {         for (DirectedGraphNode child : children) {             child.parents.remove(this);         }          for (DirectedGraphNode parent : parents) {             parent.children.remove(this);         }          addEdges(-children.size());         addEdges(-parents.size());         children.clear();         parents.clear();     }      @Override     public String toString() {         return "[DirectedGraphNode "" + getName() + ""]";     } } 0  

Índice que utilizo en esta consulta

  package net.coderodde.graph.support;  import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import net.coderodde.graph.AbstractGraphNode;  /**  * This class implements a directed graph node.  *   * @author Rodion "rodde" Efremov  * @version 1.6 (Oct 11, 2015)  */ public class DirectedGraphNode extends AbstractGraphNode<DirectedGraphNode> {      private final Set<DirectedGraphNode> children = new LinkedHashSet<>();     private final Set<DirectedGraphNode> parents  = new LinkedHashSet<>();      private final Set<DirectedGraphNode> childrenWrapper =              Collections.<DirectedGraphNode>unmodifiableSet(children);      private final Set<DirectedGraphNode> parentsWrapper =              Collections.<DirectedGraphNode>unmodifiableSet(parents);      /**      * Constructs a new directed graph node with given name.      *       * @param name the name of the node.      */     public DirectedGraphNode(String name) {         super(name);     }      @Override     public void addChild(DirectedGraphNode child) {         checkNodeBelongsToGraph();          if (child == null) {             return;         }          children.add(child);         child.parents.add(this);         addEdges(1);     }      @Override     public boolean hasChild(DirectedGraphNode node) {         return children.contains(node);     }      @Override     public boolean hasParent(DirectedGraphNode node) {         return parents.contains(node);     }      @Override     public void removeChild(DirectedGraphNode node) {         if (node == null) {             return;         }          if (node.getOwnerGraph() != this.getOwnerGraph()) {             return;         }          if (!children.contains(node)) {             return;         }          children.remove(node);         node.parents.remove(this);         addEdges(-1);     }      @Override     public Set<DirectedGraphNode> children() {         return childrenWrapper;     }      @Override     public Set<DirectedGraphNode> parents() {         return parentsWrapper;     }      @Override     public void clear() {         for (DirectedGraphNode child : children) {             child.parents.remove(this);         }          for (DirectedGraphNode parent : parents) {             parent.children.remove(this);         }          addEdges(-children.size());         addEdges(-parents.size());         children.clear();         parents.clear();     }      @Override     public String toString() {         return "[DirectedGraphNode "" + getName() + ""]";     } } 1  

¿Cómo puedo hacer que funcione más rápido, sea más estable? ¿Hay algo mal con mi código SQL o el código PHP? Este código realmente está matando a la CPU ...

Sin este índice, la consulta es de alrededor de 0.5 segundos (PHPYMYADMIN EXEC. Tiempo. 1.5 segundos al llamar con AJAX).

¡Perdón por mi mal inglés! ^ _ ^

Original en ingles

I'm developing a fully AJAX community WP theme that comes with a lot of custom queries.

Everything is fine, there is no bug but recently but I had a few clients that have a huge database and my theme started to kill the CPU. I wonder how can I make it run faster.

What this code is doing?

This code is trying to get posts that contains only have "comment" type comments (comment_type="comment") AND approved ones.

database information: Mysql - mariaDB

table name I'm trying to get result - wp_comments

how many data that table have - 380.000 (380K) comments

query's raw output time on phpmyadmin (w/o php) - 0.23 seconds

time to get this data on front end - 0.85-90 seconds

JS Code that calls function

    function lfload(page) {   $("#sol-load").css("opacity","0.75");   document.cookie = "lf= popular;  expires = Fri, 31 Dec 9999 23:59:59 GMT; path=/";   document.cookie = "popular_page = " + page + ";  expires = Fri, 31 Dec 9999 23:59:59 GMT; path=/";   var xhr = new XMLHttpRequest();   xhr.open("POST", bilgi.tema_url + '/admin-ajax.php', true);   xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");   xhr.onreadystatechange = function() {     if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {       document.getElementById("sol-load").innerHTML = this.response;       $("#sol-load").css("opacity","1");   }   }   xhr.send("action=popular_ajax"); } 

PHP Code to get data

function popular_ajax()   {           global $wpdb;            // getting latest page from cookie           if (isset($_COOKIE["popular_page"]) AND            $_COOKIE["popular_page"] != 0) {               $latest_sent_page_no = intval($_COOKIE["popular_page"]);           } elseif (!isset($_COOKIE["popular_page"]) OR            $_COOKIE["popular_page"] == 0) {               $latest_sent_page_no = 1;           }           $page = $latest_sent_page_no;           $cur_page = $page;           $page -= 1;           $per_page = 20;           $start = $page * $per_page;           $count_limiti = $per_page*50;            // tried to limit count            //query to make it more faster but did'nt work           // count how many page exists to use it for pagination           $count = $wpdb->get_var("SELECT COUNT(DISTINCT comment_post_ID)            FROM ".$wpdb->prefix."comments            USE INDEX (left_frame_index)             WHERE comment_approved = 1             AND comment_type = 'comment'             LIMIT $count_limiti");           $sorgu = $wpdb->get_results("SELECT DISTINCT comment_post_ID              FROM ".$wpdb->prefix."comments            USE INDEX (left_frame_index)            WHERE comment_approved = 1            AND comment_type = 'comment'             GROUP BY comment_post_ID             ORDER BY MAX(comment_date)             DESC LIMIT $start, $per_page");           // GET DATA FROM SQL           foreach($sorgu as $goflying2){               // xc3x87xc4xb1ktxc4xb1 bxc3xb6lgesi               $msg .= "<li class='has-border-bottom'><a class='pr-0 pl-0 pt-1                pb-2 is-size-8'                href='". get_permalink($goflying2->comment_post_ID) ."'                 title='".get_the_title($goflying2->comment_post_ID)."'>                 ".get_the_title($goflying2->comment_post_ID)."<span class='badge'>                 " .clean_comment_count_wo_newbies($goflying2->comment_post_ID).                  "</span></a></li>";           }           wp_reset_postdata();           // SAY THERE IS NO DATA IF ITS EMPTY           if ($count == 0) {             echo '<div class="tag has-text-centered has-fullwidth">             <a class="pr-0 pl-0 pt-2 pb-2 is-size-8 has-text-dark">             '.__("gxc3xbcndemimiz boxc5x9f...", 'hype-community').'</a></div>';               exit;           }           // PAGINATOIN STARTING HERE           $no_of_paginations = ceil($count / $per_page);           $start_loop = 1;           $end_loop = $no_of_paginations;           //conditional pagination           if ($cur_page > 1) {               $pre = $cur_page - 1;               $pag_container .= "               <button onclick='gundemNav(this)' value='$pre' class='button is-small'>                 <i class='fa fa-angle-left' aria-hidden='true'></i>               </button>               ";           }              $pag_container .= "           <div class='dropdown is-hoverable has-fullwidth'>         <button class='button is-small ml-3 mr-3 dropdown-trigger          has-fullwidth' aria-haspopup='true' aria-controls='dropdown-menu5'>            <span>$cur_page</span>            <span class='icon'>     <i class='fa fa-caret-down'></i>          </span>             </button>               ".'<div class="dropdown-menu" id="dropdown-menu5" role="menu">       <div class="dropdown-content">';       // tried to limit for loop           if ($end_loop > 50) {               $end_loop = 50;           }           for ($i = $start_loop; $i <= $end_loop; $i++) {             // loop to print all page numbers               if ($cur_page == $i) {                   $pag_container .= "<a value='$i' class='dropdown-item                    is-active'>$i</a>";               } else {                   $pag_container .= "<a onclick='gundemNav(this)' value='$i'                    class='dropdown-item'>$i</a>";               }           }           $pag_container = $pag_container . "   </div></div>           </div>";           if ($cur_page < $no_of_paginations) {             //conditional pagination output               $nex = $cur_page + 1;               $pag_container .= "               <button onclick='gundemNav(this)' value='$nex' class='button is-small'>                 <i class='fa fa-angle-right' aria-hidden='true'></i>               </button>               ";           }           if ($no_of_paginations == 1) {             //conditional pagination output               print     '<aside class="menu"><ul class="menu-list">' . $msg .                '</ul></aside>';           } elseif ($cur_page == 1 and $no_of_paginations >= 2) {             //conditional pagination output               print     '<aside class="menu"><ul class="menu-list">' . $msg .                '</ul></aside>';               echo  '               <button onclick="gundemNav(this)" value="'. $nex .'"                class="button is-small is-bg-blue has-text-white is-fullwidth mt-3">                 <span class="icon">                   <i class="fa fa-book" aria-hidden="true"></i>                 </span>                 <strong>'.__("fazlasxc4xb1nxc4xb1 yxc3xbckle", 'hype-community').'</strong>               </button>               ';           } elseif ($cur_page != 1 and $no_of_paginations > 1) {               //conditional pagination output               echo            '<div class="has-text-centered is-flex mb-3">'.$pag_container .             '</div>'. // pagination           '<aside class="menu"><ul class="menu-list">' . $msg .            '</ul></aside>'; // content that called from wpdb get results           }           // kill ajax           exit;   } 

INDEX I used in this query

left_frame_index -> commenst_post_ID, comment_date, comment_approved, comment_type 

How can I make it run faster, be more stable? Is there something wrong with my SQL code or PHP code? This code is really killing the CPU...

Without this index, query is around 0.5 seconds (phpymyadmin exec. time. 1.5 seconds when calling with AJAX).

sorry for my bad English! ^_^

              
         
         

Lista de respuestas

2
 
vote
  SELECT  COUNT(DISTINCT comment_post_ID)     FROM  ".$wpdb->prefix."comments USE INDEX (left_frame_index)     WHERE  comment_approved = 1       AND  comment_type = 'comment'     LIMIT  $count_limit   

necesita un índice mejor; ver el siguiente.

No compare un VARCHAR (como comment_approved ) con un literal numérico (como 1 ), el índice no se puede utilizar. Cotizaciones alrededor de "1" o '1' .

deshacerse de la "Pista de índice"; Puede ser lastimado más que ayudar.

¿Por qué no ORDER BY ? Un límite sin un pedido, le da filas "aleatorias".

OOPS, el problema real es que la consulta genera solo 1 fila, por lo que no hay uso en tener un 9988777665544336 . Mantenga el DISTINCT ; Tirar el LIMIT .

  SELECT  DISTINCT comment_post_ID     FROM  ".$wpdb->prefix."comments USE INDEX (left_frame_index)     WHERE  comment_approved = 1       AND  comment_type = 'comment'     GROUP BY  comment_post_ID     ORDER BY  MAX(comment_date) DESC     LIMIT  $start, $per_page   

ver arriba, más

No mezcle comment_approved0 y comment_approved1 . Use solo el comment_approved2 .

Esta consulta necesita un índice diferente (use el orden especificado):

  comment_approved3  

Sospecho que esta consulta no te está dando lo que esperas? Por favor describa en inglés lo que es el objetivo.

Paginación a través de comment_approved4 tiene problemas. Consulte http://mysql.rjweb.org/doc.php/pagination

 
SELECT  COUNT(DISTINCT comment_post_ID)     FROM  ".$wpdb->prefix."comments USE INDEX (left_frame_index)     WHERE  comment_approved = 1       AND  comment_type = 'comment'     LIMIT  $count_limit 

Needs a better index; see the below.

Do NOT compare a VARCHAR (such as comment_approved) with a numeric literal (such as 1), the index cannot be used. Put quotes around "1" or '1'.

Get rid of the "index hint"; it may be hurting more than helping.

Why no ORDER BY? A limit without an order-by give you "random" rows.

Oops, the real problem is that the query generates only 1 row, so there is no use in having a LIMIT. Keep the DISTINCT; toss the LIMIT.

SELECT  DISTINCT comment_post_ID     FROM  ".$wpdb->prefix."comments USE INDEX (left_frame_index)     WHERE  comment_approved = 1       AND  comment_type = 'comment'     GROUP BY  comment_post_ID     ORDER BY  MAX(comment_date) DESC     LIMIT  $start, $per_page 

See above, plus

Don't mix GROUP BY and DISTINCT. Use only the GROUP BY.

This query needs a different index (use the specified order):

INDEX(comment_type, comment_approved, comment_post_ID, comment_date) 

I suspect this query is not giving you what you expect? Please describe in English what the goal is.

Pagination via OFFSET has problems. See http://mysql.rjweb.org/doc.php/pagination

 
 
1
 
vote

Comentarios generales

En general, diría que la práctica de enviar HTML en una respuesta AJAX y usarlo para establecer directamente el contenido de un elemento DOM es una práctica anticuada, y podría ser una avenida XSS . Mientras que la práctica de Envío de datos de la API y que tiene la construcción del código de extremo delantero, el HTML puede haber sido una nueva construcción hace ocho años es mucho más común en la web de hoy.

Mejora de la velocidad de código a las publicaciones de búsqueda

Para responder a su pregunta " cómo puedo hacerlo más más rápido, más estable. " Parece que hay una consulta para obtener identificaciones para cada publicación, y luego en el bucle para crear elementos de la lista , hay llamadas a get_permalink() , get_the_title()1 y clean_comment_count_wo_newbies() . ¿Esas llamadas de función ejecutan consultas contra la base de datos? Si es así, eso probablemente sería el cuello de botella. Idealmente, el código ejecutaría una sola consulta para obtener toda la información necesaria, por ejemplo. IDS, títulos, conteos de comentarios, etc. Recuerde que las consultas de DB son caras , por lo que es mejor minimizar el número de consultas necesarias.

JavaScript

Dom Access

El código busca el elemento con ID SOL-CARD tres veces dentro de unas pocas líneas. Sería prudente cachear esas miradas, ya que pueden ser caras.

puente peaje

"... El acceso a Dom es realmente bastante costoso: lo pienso como si tengo un puente, como dos trozos de tierra con un puente de peaje, y el motor JavaScript está en un lado, y el DOM está por el otro, y cada vez que quiero acceder al DOM desde el motor JavaScript, tengo que pagar ese peaje "
- John Hrvatin, Microsoft, Mix09, en Esta charla Construyendo aplicaciones web de alto rendimiento y Sitios a las 29:38, también citadas en el o'reilly javascript libro de Nicholas C Zakas Pg 36 , así como se menciona en esta publicación

  const solLoad = $("#sol-load");   

AJAX

El código de extremo delantero utiliza jquery para acceder a los elementos DOM, pero el código AJAX utiliza mecanismos de vainilla XHR. Los métodos de jQuery Ajax como $.get() y $.post() podría usarse para simplificar el código. En realidad 9988776655544336 se puede usar para simplificar el código dramáticamente -

No he probado esto, pero esto debería ser lo que sería necesario:

  solLoad.load(bilgi.tema_url + '/admin-ajax.php', {action: 'popular_ajax'},      solLoad.css.bind(solLoad, "opacity", 1));   

Manipuladores de eventos en línea

Hay manipuladores de eventos registrados dentro del código HTML - E.G.

  <button onclick='gundemNav(this)'   

Es mejor registrar los manejadores de eventos dentro del JavaScript (por ejemplo, usando button.addEventListener (se puede hacer cuando se crea el elemento o después se selecciona a través de DOM) por múltiples razones:

  1. La lógica puede separarse de la marca: si varios compañeros de equipo trabajaron en el proyecto, entonces uno podría trabajar en el JavaScript mientras que el otro podría funcionar en el HTML de forma independiente.
  2. Dichos manipuladores pueden contaminar el espacio de nombres global que puede llevar a un comportamiento extraño .
 

Overall comments

Overall Ixe2x80x99d say that the practice of sending HTML in an AJAX response and using that to directly set the content of a DOM element is an antiquated practice, and could be an XSS avenue. While the practice of sending data from the API and having the front end code construct the HTML dynamically may have been a new construct eight years ago it is much more common in todayxe2x80x99s web.

Improving speed of code to lookup posts

To answer your question "How can I make it more faster, more stable." it looks like there is a query to get IDs for each post, and then in the loop to create list items, there are calls to get_permalink(), get_the_title() and clean_comment_count_wo_newbies(). Do those function calls run queries against the database? If so, that would likely be the bottleneck. Ideally the code would run a single query to get all the information needed - e.g. IDs, titles, comment counts, etc. Remember that DB queries are expensive so it is best to minimize the number of queries needed.

JavaScript

DOM Access

The code looks up the element with id sol-load three times within a few lines. It would be wise to cache those lookups, since they can be expensive.

bridge toll

xe2x80x9d...DOM access is actually pretty costly - I think of it like if I have a bridge - like two pieces of land with a toll bridge, and the JavaScript engine is on one side, and the DOM is on the other, and every time I want to access the DOM from the JavaScript engine, I have to pay that tollxe2x80x9d
xc2xa0xc2xa0xc2xa0xc2xa0- John Hrvatin, Microsoft, MIX09, in this talk Building High Performance Web Applications and Sites at 29:38, also cited in the O'Reilly Javascript book by Nicholas C Zakas Pg 36, as well as mentioned in this post

const solLoad = $("#sol-load"); 

AJAX

The front end code uses jQuery to access DOM elements yet the AJAX code uses vanilla XHR mechanisms. The jQuery AJAX methods like $.get() and $.post() could be used to simplify the code. Actually .load() can be used to simplify the code dramatically -

I haven't tested this but this should be what would be needed:

solLoad.load(bilgi.tema_url + '/admin-ajax.php', {action: 'popular_ajax'},      solLoad.css.bind(solLoad, "opacity", 1)); 

Inline event handlers

There are event handlers registered within the HTML code - e.g.

<button onclick='gundemNav(this)' 

It is better to register event handlers within the JavaScript (e.g. using button.addEventListener (can be done when element is created or after is is selected via DOM) for multiple reasons:

  1. The logic can be separated from the markup - if multiple teammates worked on the project then one could work on the JavaScript while the other could work on the HTML independently.
  2. Such handlers can pollute the global namespace which can lead to strange behavior.
 
 

Relacionados problema

6  ¿Modificar los bucles personalizados para mejorar la legibilidad y la eficiencia para WordPress?  ( Modify custom loops to improve readability and efficiency for wordpress ) 
El siguiente código recupere los tipos de publicaciones personalizadas con su taxonomía personalizada. Solo soy un principiante en PHP y me gustaría saber c...

5  Mostrando todas las publicaciones individuales  ( Displaying all single posts ) 
Creo que hay algunos problemas de sangría confusa y extraños en este archivo de WordPress (single.php). ¿Alguna sugerencia sobre la mejora de la sangría y la ...

1  Conversión CSV a MySQL con PHP en mi complemento de WordPress personalizado  ( Converting csv to mysql with php in my custom wordpress plugin ) 
Tengo una función que convierte un archivo de CSV a MYSQL El archivo podría ser de 5,000 filas de largo hasta 90,000 filas de largo. Sobre la base de qu...

3  Cree un sitio de sitio de WordPress con los datos de la aplicación NGINX automáticamente  ( Create a wordpress site data with nginx app data automatically ) 
El siguiente script está dirigido a Ubuntu >=16.04 LEMP entornos con PHP-FPM 9988777665544335 , MySQL, WP-CLI, CertBot y WordPress Apps. El script Obteng...

2  Visualización de campos en una barra lateral de una plantilla de página personalizada  ( Displaying fields in a sidebar of a custom page template ) 
Estoy comenzando con la programación de PHP y apreciaría una crítica en mi código y cómo podría hacerlo más eficiente, en lugar de repetir las declaraciones ...

3  Exportación de datos en un widget de WordPress  ( Exporting data in a wordpress widget ) 
Tengo algunas tablas personalizadas en una base de datos de WordPress que necesito para exportar a CSV. Creé un widget de Dashboard para ayudarlo con esto en ...

4  Añadir campos de perfil de usuario  ( Add user profile fields ) 
Tengo esta función PHP que agrega campos de perfil de usuario personalizados a WordPress. Guarda el campo a través del archivo WOOCOMMERCE FORM-EDIT-MY-CUENTA...

6  Determinar el valor en el rango, inyectar a HTML que se utilizará en CSS  ( Determine value in range inject to html to be used in css ) 
Quiero mostrar a los usuarios qué paquete están, según cuántos artículos tienen en su carrito. El código funciona, pero me pregunto si algo puede mejorarse. ...

1  Script de cuatro líneas para hacer una copia de seguridad inmediata de DB y Document Root  ( Four lines script to make an immediate db and document root zip backup ) 
¿Qué piensas de mi script para hacer una copia de seguridad inmediata de DB y DOCUMENTE ROOT ROOT? Cualquier falla que puedas encontrar. Por favor, infórmeme ...

1  Botón para seguir / dejar de seguir un usuario  ( Button to follow unfollow a user ) 
Como principiante en la codificación, acabo de escribir este código. El código debe agregar un formulario con un botón a cada perfil de usuario, llamado Sig...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos