¿Por qué el conteo (*) es lento, cuando explicar sabe la respuesta?


14

Esta consulta: select count(*) from planner_eventtarda mucho tiempo en ejecutarse; tanto tiempo, me di por vencida y la maté antes de que terminara. Sin embargo, cuando ejecuto explain select count(*) from planner_event, puedo ver una columna en la salida con el número de filas (14 m).

¿Cómo es que explicar puede obtener el número de filas al instante, pero cuenta (*) tarda mucho tiempo en ejecutarse?


COUNT (*) sin una causa WHERE provocará un escaneo de la tabla en el motor InnoDB. MyISAM puede entregar el recuento directamente porque el COUNT se mantiene en el archivo de encabezado fuera de la tabla.
Raymond Nijland el

Respuestas:


16

Explain está utilizando estadísticas recopiladas previamente (utilizadas por el optimizador de consultas). Hacer un select count(*)lee CADA bloque de datos.

Aquí hay una forma económica de obtener un recuento estimado de filas:

select TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='planner_event';

Incluso si lo hiciera select count(id), podría llevar mucho tiempo, a menos que tenga un índice secundario id(también suponiendo que ides una CLAVE PRIMARIA). Debido a que todos los datos (incluidos los datos de fila) se almacenan en índices de B-Tree, realizar un select count(PK_COLUMN)todavía es una cantidad considerable de E / S (necesita leer todas las páginas de datos). Si tiene un índice secundario en el campo PK, podrá realizar menos IO para realizar un recuento.


I_S.TABLES le da la misma estimación que EXPLAINle da.
Rick James

Falta la consulta AND TABLE_SCHEMA='my_database'; de lo contrario, obtendrá varios resultados si tiene una tabla con el mismo nombre en otra base de datos.
cz

3

Explain obtiene el número de algunas "estadísticas" que se utilizan para estimar cosas para el Optimizador. Ese número puede estar lejos de ser correcto: a veces veo que es más que un factor de 2 (mayor o menor) que el valor exacto.

La ejecución COUNT(*)de una tabla InnoDB debe escanear la tabla para evitar contar incorrectamente los registros que están ocupados siendo insertados / eliminados por otras conexiones pero aún no "confirmados". En realidad, es lo suficientemente bueno para hacer un análisis completo de algún índice, no necesariamente toda la tabla (que contiene el PRIMARY KEY).

¿Cuánta RAM tienes? ¿Cuál es el valor de innodb_buffer_pool_size? Podría ayudar si eso fuera aproximadamente el 70% de la RAM.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.