Cuestionario: Deep Postgres: Parte 2
¿Eres un SQL Steele? ¿O un SQL Softie?
Parte 2 de 2. Volver a la Parte 1
¡Bienvenido a la Parte 2 de mi cuestionario avanzado de PostgreSQL!
Este cuestionario combina características conocidas y menos documentadas de PostgreSQL y sus trampas: JOIN, NULL, ANSI SQL, Transacciones, Internos, Indexación, Muestreo de datos… ¡y mucho más!
¡Buena suerte! 🍀
¿Cuál no es ❌ una expresión JOIN válida de PostgreSQL?
Sabías de CROSS JOIN, ¿verdad?
¿Te hizo pensar el JOIN ALL en otra operación, UNION ALL?
La respuesta aquí es JOIN ALL ❌.
Los tipos de JOIN correctos son:
INNER JOIN(JOIN por defecto)LEFT JOIN(oLEFT OUTER JOIN)RIGHT JOIN(oRIGHT OUTER JOIN)FULL JOIN(oFULL OUTER JOIN)CROSS JOIN(el producto cartesiano, a menos que una cláusulaWHEREposterior lo filtre)
Excepto por “Depende de los efectos secundarios” ¿Qué ocurre después de un error?
BEGIN;UPDATE students SET status = 'alumni' WHERE grade = 12;UPDATE students SET graduation_date = CURRENT_DATE WHERE grade = 12;UPDATE students SET grade = 'GRADUATED'; -- 🚨 Error: type mismatchCOMMIT;Cuando ocurre un error aquí:
- La transacción completa se revierte
- No se confirman cambios
- La transacción se marca como fallida
Para confirmar parcialmente:
BEGIN;UPDATE ...;SAVEPOINT my_save;UPDATE ...; -- ErrorROLLBACK TO my_save;COMMIT;¿Qué condición ON puede usar PostgreSQL para un HASH JOIN?
SELECT *FROM students aJOIN grades bON /* What goes here? ⁉ */;Un hash join es posible con una condición de igualdad (=) en la cláusula ON.
=es la forma de predicado clave para los hash joins>y>=no son predicados de hash joinHASH JOINno es una sintaxis válida en PostgreSQL
El planificador aún puede elegir un bucle anidado o un merge join según el tamaño de la tabla, las estadísticas, los índices y la configuración de memoria.
¿Cuál es correcta para nombres de columnas sensibles a mayúsculas?
CREATE TABLE grades ( "Student Name" VARCHAR(100), 'Student Grade' INTEGER);En PostgreSQL:
- Las comillas dobles (
") se usan para identificadores (nombres de tablas, nombres de columnas) - Las comillas simples (
') se usan para literales de cadena
Buenas prácticas:
- Evita mayúsculas mezcladas o espacios en los nombres
- Usa snake_case para los identificadores
- Sólo usa identificadores entre comillas cuando sea absolutamente necesario
¿Cómo especificas un nombre de columna que contiene un punto?
CREATE TABLE teachers ( id INT GENERATED BY DEFAULT AS IDENTITY, first.name TEXT, -- How do you include the column: first.name? salary NUMERIC);PostgreSQL usa comillas dobles para citar identificadores:
- Comillas dobles
"..."para identificadores (nombres de columnas, nombres de tablas) - Comillas simples
'...'para literales de cadena - La forma
first.namese interpreta comotable_name.column_name
Sin comillas, un punto en un nombre de columna se interpretaría como separador de esquema/tabla! Además, todos los identificadores sin comillas se convierten a minúsculas por defecto.
Para evitar sorpresas, lo mejor es usar snake_case y evitar caracteres especiales.
¿Cuál es la sintaxis válida para muestrear aleatoriamente el 10% de los estudiantes?
Esta es complicada! Tiene alrededor de 6 trampas, algunas incluyen:
- Descripción de alto nivel + fragmentos de sintaxis. Prueba cómo adaptas y ensamblas información incompleta.
- Requiere conocer la sintaxis de
TABLESAMPLE, ya que ninguna de las opciones deTABLESAMPLEusa la sintaxis correcta! (¡Siniestra! Lo sé! Sigue adelante, ¡creo en ti!!! ❤️) - Los
ROW_NUMBER() OVER (ORDER BY RAND())yORDER BY RANDOM() > 10son más pistas falsas. Parecen correctos, pero no lo son.RAND()no existe. YRANDOM() > 10es una expresión booleana que siempre será falsa porqueRANDOM()siempre está en el rango0.0-1.0. Otro problema, elORDER BY RANDOM() > 10también ordenaría por un valor booleano, no por un número aleatorio. Pero ese> 10suena como si fuera un porcentaje, ¿no? BERNOULLIes válido, sin embargoSAMPLETABLEno lo es.WHERE RANDOM() >= 0.1es una trampa!RANDOM()devuelve un valor en el rango0.0 <= x < 1.0, así que>= 0.1devolvería aproximadamente el 90% de las filas, no el 10%.
En cuanto al método TABLESAMPLE, PostgreSQL soporta dos métodos de muestreo:
BERNOULLI: Cada fila tiene igual probabilidadSYSTEM: Muestreo a nivel de bloque (más rápido pero menos aleatorio)
Para aprender más sobre muestreo, revisa este artículo de Render.
Ejemplo:
-- Sample 10% of rowsSELECT * FROM students TABLESAMPLE BERNOULLI (10);
-- For repeatable results, use REPEATABLE:SELECT * FROM studentsTABLESAMPLE BERNOULLI (10) REPEATABLE (42);También vale mencionar que TABLESAMPLE ha sido reportado como no muy aleatorio. Si necesitas una muestra fija más aleatoria, considera usar ORDER BY RANDOM() LIMIT 10. Pero ten en cuenta que esto devuelve 10 filas, no el 10%, y puede ser lento en tablas grandes.
Existen también extensiones de terceros que ofrecen mejores métodos de muestreo aleatorio, pero eso está fuera del alcance de este ejercicio! 😅
¿Qué hace EXPLAIN ANALYZE con las sentencias UPDATE?
EXPLAIN ANALYZEUPDATE studentsSET grade = grade + 1WHERE status = 'active';EXPLAIN ANALYZE en realidad ejecuta la consulta! Ten cuidado al analizar una operación de escritura, específicamente sentencias UPDATE, DELETE y INSERT. Puede que necesites ejecutar operaciones de limpieza después de cada EXPLAIN ANALYZE para obtener resultados repetibles.
Mejores prácticas:
- Usa
EXPLAIN(sin ANALYZE) para UPDATE/DELETE/INSERT - Envuelve las modificaciones en transacciones:
BEGIN;EXPLAIN ANALYZE ...;ROLLBACK;¡Bien hecho! ¡Has profundizado en varias áreas de PostgreSQL! 🐘
Espero que hayas aprendido algo nuevo, o al menos que tengas una puntuación de la que presumir. 🏆
¿Quieres más emociones en la vida? Consulta mi Colección de Quiz para diversión sin fin*.
