tag strip_tags remove name ejemplo all php sql postgresql window-functions sql-limit

php - remove - strip_tags wordpress



La mejor forma de obtener el recuento de resultados antes de aplicar LIMIT (5)

Al buscar datos que provienen de un DB, necesita saber cuántas páginas habrá para hacer que la página controle el salto.

Actualmente lo hago ejecutando la consulta dos veces, una vez envuelto en un count() para determinar el total de resultados, y una segunda vez con un límite aplicado para recuperar solo los resultados que necesito para la página actual.

Esto parece ineficiente. ¿Hay una forma mejor de determinar cuántos resultados se habrían devuelto antes de aplicar LIMIT ?

Estoy usando PHP y Postgres.


Puro SQL

Las cosas han cambiado desde 2008. Puede usar una función de ventana para obtener el conteo completo y el resultado limitado en una consulta. (Introducido con PostgreSQL 8.4 en 2009 ).

SELECT foo , count(*) OVER() AS full_count FROM bar WHERE <some condition> ORDER BY <some col> LIMIT <pagesize> OFFSET <offset>

Tenga en cuenta que esto puede ser considerablemente más caro que sin el recuento total. Deben contarse todas las filas y no es posible un acceso directo que tome solo las filas superiores de un índice coincidente.
No importa mucho con tablas pequeñas, asuntos con mesas grandes.

Caso de esquina : cuando OFFSET es al menos tan grande como el número de filas de la consulta base, no se devuelve ninguna fila . Posible alternativa:

Considera la secuencia de eventos :

  1. WHERE cláusula WHERE (y las condiciones JOIN , pero no aquí) filtra las filas calificadas de la (s) tabla (s) base.

    (Las funciones GROUP BY y agregadas irían aquí).

  2. Las funciones de ventana se aplican teniendo en cuenta todas las filas calificadas (según la cláusula OVER y la especificación de cuadro de la función). El count(*) OVER() simple count(*) OVER() se basa en todas las filas.

  3. ORDER BY

    ( DISTINCT o DISTINCT ON irían aquí).

  4. LIMIT / OFFSET se aplica según el orden establecido para seleccionar las filas a devolver.

LIMIT / OFFSET vuelve cada vez más ineficiente con un número creciente de filas en la tabla. Considere enfoques alternativos si necesita un mejor rendimiento:

Alternativas para obtener el recuento final

Existen enfoques completamente diferentes para obtener el recuento de las filas afectadas (no el recuento antes de aplicar OFFSET & LIMIT ). Postgres tiene contabilidad interna cuántas filas fueron afectadas por el último comando SQL. Algunos clientes pueden acceder a esa información o contar filas ellos mismos (como psql).

Por ejemplo, puede recuperar el número de filas afectadas en plpgsql inmediatamente después de ejecutar un comando SQL con:

GET DIAGNOSTICS integer_var = ROW_COUNT;

Detalles en el manual.

O puede usar pg_num_rows en PHP . O funciones similares en otros clientes.

Relacionado:


Como debe saberlo con el propósito de buscar, le sugiero que ejecute la consulta completa una vez, escribiendo los datos en el disco como un caché del lado del servidor y luego dándolos a través de su mecanismo de búsqueda.

Si está ejecutando la consulta COUNT con el fin de decidir si debe proporcionar los datos al usuario o no (es decir, si hay registros> X, devuelve un error), debe seguir con el enfoque COUNT.


Como describo en mi blog , MySQL tiene una característica llamada SQL_CALC_FOUND_ROWS . Esto elimina la necesidad de hacer la consulta dos veces, pero aún necesita hacer la consulta en su totalidad, incluso si la cláusula de límite le hubiera permitido detenerse antes.

Hasta donde yo sé, no existe una característica similar para PostgreSQL. Una cosa a tener en cuenta al hacer paginación (lo más común para el cual se usa LIMIT en mi humilde opinión): hacer un "OFFSET 1000 LIMIT 10" significa que el DB tiene que buscar al menos 1010 filas, incluso si solo le da 10. Una forma más efectiva de hacerlo es recordar el valor de la fila por la que está ordenando para la fila anterior (el número 1000 en este caso) y reescribir la consulta de esta manera: "... WHERE order_row> value_of_1000_th LIMIT 10". La ventaja es que "order_row" probablemente esté indexado (si no, tienes un problema). La desventaja es que si se agregan nuevos elementos entre las visitas a la página, esto puede desconocerse un poco (pero, una vez más, puede no ser observable por los visitantes y puede representar un gran aumento en el rendimiento).


Dado que Postgres ya hace una cierta cantidad de cosas en el caché, este tipo de método no es tan ineficiente como parece. Definitivamente no duplica el tiempo de ejecución. Tenemos temporizadores incorporados en nuestra capa de DB, así que he visto la evidencia.


Podría mitigar la penalización de rendimiento al no ejecutar la consulta COUNT () cada vez. Guarde en caché el número de páginas para, por ejemplo, 5 minutos antes de que la consulta se ejecute de nuevo. A menos que esté viendo una gran cantidad de INSERT, eso debería funcionar bien.