La siguiente consulta en un extranjero tarda unos 5 segundos en ejecutarse en 3,2 millones de filas:
SELECT x."IncidentTypeCode", COUNT(x."IncidentTypeCode")
FROM "IntterraNearRealTimeUnitReflexes300sForeign" x
WHERE x."IncidentDateTime" >= '05/01/2016'
GROUP BY x."IncidentTypeCode"
ORDER BY 1;
Cuando ejecuto la misma consulta en la tabla normal, regresa en .6 segundos. Los planes de ejecución son bastante diferentes:
Tabla normal
Sort (cost=226861.20..226861.21 rows=4 width=4) (actual time=646.447..646.448 rows=7 loops=1)
Sort Key: "IncidentTypeCode"
Sort Method: quicksort Memory: 25kB
-> HashAggregate (cost=226861.12..226861.16 rows=4 width=4) (actual time=646.433..646.434 rows=7 loops=1)
Group Key: "IncidentTypeCode"
-> Bitmap Heap Scan on "IntterraNearRealTimeUnitReflexes300s" x (cost=10597.63..223318.41 rows=708542 width=4) (actual time=74.593..342.110 rows=709376 loops=1)
Recheck Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone)
Rows Removed by Index Recheck: 12259
Heap Blocks: exact=27052 lossy=26888
-> Bitmap Index Scan on idx_incident_date_time_300 (cost=0.00..10420.49 rows=708542 width=0) (actual time=69.722..69.722 rows=709376 loops=1)
Index Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone)
Planning time: 0.165 ms
Execution time: 646.512 ms
Tabla extranjera
Sort (cost=241132.04..241132.05 rows=4 width=4) (actual time=4782.110..4782.112 rows=7 loops=1)
Sort Key: "IncidentTypeCode"
Sort Method: quicksort Memory: 25kB
-> HashAggregate (cost=241131.96..241132.00 rows=4 width=4) (actual time=4782.097..4782.100 rows=7 loops=1)
Group Key: "IncidentTypeCode"
-> Foreign Scan on "IntterraNearRealTimeUnitReflexes300sForeign" x (cost=10697.63..237589.25 rows=708542 width=4) (actual time=1.916..4476.946 rows=709376 loops=1)
Planning time: 1.413 ms
Execution time: 4782.660 ms
Creo que estoy pagando un alto precio por la GROUP BY
cláusula, que no se pasa al servidor extranjero cuando EXPLAIN VERBOSE
:
SELECT
"IncidentTypeCode"
FROM
PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
WHERE
(
(
"IncidentDateTime" >= '2016-05-01 00:00:00' :: TIMESTAMP WITHOUT TIME ZONE
)
)
Esto devuelve 700k filas. ¿Hay alguna forma de evitar esto?
Ayer pasé mucho tiempo leyendo esta página de documentación y pensé que había encontrado mi respuesta con la configuración use_remote_estimate
de verdadero, pero no tuvo ningún efecto.
Tengo acceso al servidor externo para crear objetos si es necesario. El valor de la marca de tiempo en la WHERE
cláusula puede ser cualquier cosa; no proviene de una lista de valores predefinidos.
IntterraNearRealTimeUnitReflexes300sForeign
frenteIntterraNearRealTimeUnitReflexes300s
yidx_incident_date_time_300
presumo los 300s son los mismos, pero podría ser la pena comprobar si elidx_incident_date_time_300
existe índice en el servidor extranjeraRespuestas:
Si usa,
use_remote_estimate
asegúrese de ejecutar ANALYZE la tabla extranjera (veo estimaciones bastante cercanas a las devueltas, probablemente lo haya hecho). Además, las mejoras pushdown no están disponibles en la versión <9.5. También supongo que tiene la misma estructura de tabla en el servidor remoto (incluidos los índices). Si se necesita un mapa de bits debido a la baja cardinalidad, no utilizará el índice debido a las limitaciones del mecanismo de pushdown. Es posible que desee reducir la cantidad de filas devueltas para forzar una exploración de índice BTREE ( intervalos de marca de tiempo)) Desafortunadamente, no hay una forma limpia de evitar SeqScan en el servidor remoto si el filtro devuelve + 10% de las filas de la tabla (puede variar este porcentaje si el planificador considera que escanear toda la tabla es más barato que buscar lecturas). Si está utilizando SSD, probablemente le resultará útil modificarrandom_page_cost
).Puede usar CTE para aislar el comportamiento GROUP BY:
fuente