¿Cómo obligo a Postgres a usar un índice cuando, de lo contrario, insistiría en hacer un escaneo secuencial?
sql
postgresql
indexing
micro
fuente
fuente
Respuestas:
Suponiendo que está preguntando acerca de la característica común de "sugerencias de índice" que se encuentra en muchas bases de datos, PostgreSQL no proporciona dicha característica. Esta fue una decisión consciente tomada por el equipo de PostgreSQL. Puede encontrar una buena descripción general de por qué y qué puede hacer en su lugar aquí . Las razones son básicamente que es un truco de rendimiento que tiende a causar más problemas en el futuro a medida que cambian sus datos, mientras que el optimizador de PostgreSQL puede reevaluar el plan en función de las estadísticas. En otras palabras, lo que hoy podría ser un buen plan de consulta probablemente no será un buen plan de consulta para siempre, y las sugerencias de índice fuerzan un plan de consulta particular para siempre.
Como martillo muy contundente, útil para realizar pruebas, puede utilizar los parámetros
enable_seqscan
yenable_indexscan
. Ver:enable_
parámetrosEstos no son adecuados para un uso de producción continuo . Si tiene problemas con la elección del plan de consultas, debe consultar la documentación para rastrear los problemas de rendimiento de las consultas . No se limite a establecer
enable_
parámetros y alejarse.A menos que tenga una muy buena razón para usar el índice, es posible que Postgres esté tomando la decisión correcta. ¿Por qué?
Vea también esta antigua publicación del grupo de noticias .
fuente
Probablemente la única razón válida para usar
es cuando está escribiendo consultas y desea ver rápidamente cuál sería realmente el plan de consulta si hubiera grandes cantidades de datos en la (s) tabla (s). O, por supuesto, si necesita confirmar rápidamente que su consulta no utiliza un índice simplemente porque el conjunto de datos es demasiado pequeño.
fuente
set enable_seqscan=false
, ejecutar su consulta y luego ejecutar rápidamenteset enable_seqscan=true
para devolver postgresql a su comportamiento correcto (y obviamente no haga esto en producción, ¡solo en desarrollo!)SET SESSION enable_seqscan=false
soloA veces, PostgreSQL no puede hacer la mejor elección de índices para una condición particular. Como ejemplo, suponga que hay una tabla de transacciones con varios millones de filas, de las cuales hay varios cientos para un día determinado, y la tabla tiene cuatro índices: transaction_id, client_id, date y description. Quiere ejecutar la siguiente consulta:
PostgreSQL puede optar por utilizar el índice transaction_description_idx en lugar de transaction_date_idx, lo que puede llevar a que la consulta tarde varios minutos en lugar de menos de un segundo. Si este es el caso, puede forzar el uso del índice en la fecha modificando la condición de esta manera:
fuente
your_wanted_index
, puede ser que el motor postgresql solo realice un escaneo de secuencia / clave primaria en su lugar. Conclusión: no existe un método 100% confiable para forzar el uso de algún índice para el servidor PostgreSql.where
condición más que dos tablas o unidas y Postgres no toma el índice?Respuesta corta
Este problema suele ocurrir cuando el costo estimado de un escaneo de índice es demasiado alto y no refleja correctamente la realidad. Es posible que deba reducir el
random_page_cost
parámetro de configuración para solucionar este problema. De la documentación de Postgres :Puede verificar si un valor más bajo realmente hará que Postgres use el índice (pero use esto solo para pruebas ):
Puede restaurar el valor predeterminado con
SET random_page_cost = DEFAULT;
nuevamente.Antecedentes
Las exploraciones de índice requieren recuperaciones de páginas de disco no secuenciales. Postgres utiliza
random_page_cost
para estimar el costo de tales recuperaciones no secuenciales en relación con las recuperaciones secuenciales. El valor predeterminado es4.0
, asumiendo un factor de costo promedio de 4 en comparación con las recuperaciones secuenciales (teniendo en cuenta los efectos del almacenamiento en caché).Sin embargo, el problema es que este valor predeterminado no es adecuado en los siguientes escenarios importantes de la vida real:
1) Unidades de estado sólido
Como admite la documentación:
De acuerdo con el último punto de esta diapositiva de una charla en la PostgresConf 2018,
random_page_cost
debería establecerse en algo intermedio1.0
y2.0
para unidades de estado sólido.2) datos en caché
Si los datos de índice requeridos ya están almacenados en caché en la RAM, un escaneo de índice siempre será significativamente más rápido que un escaneo secuencial. La documentación dice:
El problema es que, por supuesto, no puede saber fácilmente si los datos relevantes ya están almacenados en caché. Sin embargo, si se consulta con frecuencia un índice específico, y si el sistema tiene suficiente RAM, es probable que los datos se almacenen en caché y se
random_page_cost
deben establecer en un valor más bajo. Tendrá que experimentar con diferentes valores y ver qué funciona para usted.Es posible que también desee utilizar la extensión pg_prewarm para el almacenamiento en caché de datos explícitos.
fuente
La pregunta en sí misma es muy inválida. Forzar (haciendo enable_seqscan = off, por ejemplo) es una muy mala idea. Puede ser útil comprobar si será más rápido, pero el código de producción nunca debería utilizar tales trucos.
En su lugar, explique el análisis de su consulta, léala y descubra por qué PostgreSQL elige un plan incorrecto (en su opinión).
Hay herramientas en la web que ayudan con la lectura, explican, analizan la salida, una de ellas es explica.depesz.com , escrita por mí.
Otra opción es unirse al canal #postgresql en la red freenode irc y hablar con los chicos que están allí para ayudarlo, ya que optimizar la consulta no es una cuestión de "hacer una pregunta, obtener una respuesta, ser feliz". es más como una conversación, con muchas cosas que comprobar, muchas cosas que aprender.
fuente
Hay un truco para presionar postgres para preferir un seqscan agregando un
OFFSET 0
en la subconsultaEsto es útil para optimizar solicitudes que vinculan tablas grandes / enormes cuando todo lo que necesita son solo los n primeros / últimos elementos.
Supongamos que está buscando los primeros / últimos 20 elementos que involucren varias tablas que tengan 100k (o más) entradas, no tiene sentido construir / vincular toda la consulta sobre todos los datos cuando lo que buscará está en los primeros 100 o 1000 entradas. En este escenario, por ejemplo, resulta 10 veces más rápido hacer un escaneo secuencial.
consulte ¿Cómo puedo evitar que Postgres incluya una subconsulta?
fuente