Recientemente les estaba explicando a mis colegas la importancia de tener una columna para clasificar los datos en una tabla de base de datos si es necesario hacerlo, por ejemplo, para datos ordenados cronológicamente. Esto resultó algo difícil porque simplemente podían volver a ejecutar su consulta aparentemente sin fin y siempre devolvería el mismo conjunto de filas en el mismo orden.
He notado esto antes y todo lo que realmente puedo hacer es insistir en que confíen en mí y no simplemente asumir que una tabla de base de datos se comportará como un archivo CSV o Excel tradicional.
Por ejemplo, ejecutar la consulta (PostgreSQL)
create table mytable (
id INTEGER PRIMARY KEY,
data TEXT
);
INSERT INTO mytable VALUES
(0, 'a'),
(1, 'b'),
(2, 'c'),
(3, 'd'),
(4, 'e'),
(5, 'f'),
(6, 'g'),
(7, 'h'),
(8, 'i'),
(9, 'j');
creará una tabla con un orden conceptual claro. Seleccionar los mismos datos de la manera más simple sería:
SELECT * FROM mytable;
Siempre me da los siguientes resultados:
id | data
----+------
0 | a
1 | b
2 | c
3 | d
4 | e
5 | f
6 | g
7 | h
8 | i
9 | j
(10 rows)
Puedo hacer esto una y otra vez y siempre me devolverá los mismos datos en el mismo orden. Sin embargo, sé que este orden implícito puede romperse, lo he visto antes, particularmente en grandes conjuntos de datos, donde algún valor aleatorio aparentemente se arrojará al lugar "incorrecto" cuando se seleccione. Pero se me ha ocurrido que no sé cómo sucede esto o cómo reproducirlo. Me resulta difícil obtener resultados en Google porque la consulta de búsqueda tiende a devolver ayuda general para ordenar los conjuntos de resultados.
Entonces, mis preguntas son esencialmente estas:
¿Cómo puedo demostrar de manera demostrable y concreta que el orden de retorno de las filas de una consulta sin una
ORDER BY
declaración no es confiable, preferiblemente al causar y mostrar un desglose del orden implícito incluso cuando la tabla en cuestión no se actualiza o edita ?¿Hay alguna diferencia si los datos solo se insertan una vez en masa y luego nunca se actualizan nuevamente?
Preferiría una respuesta basada en postgres ya que esa es la que estoy más familiarizado, pero estoy más interesado en la teoría misma.
order by
cláusula a sus consultas. ¿Están tratando de ahorrar en el almacenamiento del código fuente? desgaste del teclado? tiempo que lleva escribir la temida cláusula?Respuestas:
Veo tres formas de tratar de convencerlos:
Permítales intentar la misma consulta pero con una tabla más grande (más número de filas) o cuando la tabla se actualiza entre ejecuciones. O se insertan nuevas filas y se eliminan algunas antiguas. O se agrega o elimina un índice entre ejecuciones. O la mesa se aspira (en Postgres). O se reconstruyen los índices (en SQL Server). O la tabla se cambia de agrupada a un montón. O se reinicia el servicio de la base de datos.
Puede sugerir que demuestren que diferentes ejecuciones devolverán el mismo orden. ¿Pueden probarlo? ¿Pueden proporcionar una serie de pruebas que demuestren que cualquier consulta dará el resultado en el mismo orden, sin importar cuántas veces se ejecute?
Proporcione la documentación de varios DBMS en ese asunto. Por ejemplo:
PostgreSQL :
Servidor SQL :
Oráculo :
fuente
ORDER BY
, que garantizará el orden, sin importar cómo vaya a cambiar la tabla ? ¿Por qué no tener una caja fuerte agregada, que no hace daño?Esta es la historia del cisne negro de nuevo. Si aún no has visto uno, no significa que no existan. Esperemos que en su caso no conduzca a otra crisis financiera mundial, simplemente a unos pocos clientes descontentos.
La documentación de Postgres dice esto explícitamente:
"El sistema" en este caso comprende el propio demonio postgres (incluida la implementación de sus métodos de acceso a datos y el optimizador de consultas), el sistema operativo subyacente, el diseño lógico y físico del almacenamiento de la base de datos, posiblemente incluso cachés de CPU. Como usted, como usuario de la base de datos, no tiene control sobre esa pila, no debe confiar en que continuará comportándose para siempre como se comporta en este mismo momento.
Sus colegas están cometiendo la falacia apresurada de generalización . Para refutar su punto, es suficiente demostrar que su suposición es incorrecta solo una vez, por ejemplo, por este dbfiddle .
fuente
Considere el siguiente ejemplo, donde tenemos tres tablas relacionadas. Pedidos, usuarios y detalles del pedido. OrderDetails está vinculado con claves externas a la tabla de pedidos y la tabla de usuarios. Esta es esencialmente una configuración muy típica para bases de datos relacionales; posiblemente el propósito completo de un DBMS relacional .
Aquí, estamos consultando la tabla OrderDetails donde el UserID es 15:
El resultado de la consulta se ve así:
Como puede ver, el orden de salida de las filas no coincide con el orden de las filas en la tabla OrderDetails.
Agregar un explícito
ORDER BY
garantiza que las filas se devolverán al cliente en el orden deseado:Si el orden de las filas es imperativo, y sus ingenieros saben que el orden es imperativo, solo deberían querer usar una
ORDER BY
declaración, ya que podría costarles su designación si hubiera una falla relacionada con un orden incorrecto.Un segundo, quizá más instructivo ejemplo, utilizando la
OrderDetails
tabla de arriba, donde estamos no unirse a ninguna otra tabla, pero tiene un requisito sencillo encontrar las filas coincidentes tanto en el IdPedido y el ID de usuario, vemos el problema.Crearemos un índice para admitir la consulta, como probablemente haría en la vida real si el rendimiento es de alguna manera importante (¿cuándo no lo es?).
Aquí está la consulta:
Y los resultados:
Agregar una
ORDER BY
cláusula definitivamente asegurará que obtengamos el tipo correcto aquí también.Estas maquetas son solo ejemplos simples donde no se garantiza que las filas estén "en orden" sin una
ORDER BY
declaración explícita . Hay muchos más ejemplos como este, y dado que el código del motor DBMS cambia con bastante frecuencia, el comportamiento específico puede cambiar con el tiempo.fuente
Como ejemplo práctico, en Postgres, el orden cambia actualmente cuando actualiza una fila:
No creo que las reglas de este ordenamiento implícito existente estén documentadas en ningún lado, definitivamente están sujetas a cambios sin previo aviso y definitivamente no es un comportamiento portátil en los motores de base de datos.
fuente
No es exactamente una demostración, pero es demasiado larga para un comentario.
En tablas grandes, algunas bases de datos harán escaneos paralelos intercalados:
Si dos consultas desean escanear la misma tabla y llegar casi al mismo tiempo, la primera podría estar en la mitad de la tabla cuando comience la segunda.
La segunda consulta podría recibir registros comenzando desde el medio de la tabla (a medida que se completa la primera consulta) y luego recibir los registros desde el comienzo de la tabla.
fuente
Cree un índice agrupado que tenga el orden "incorrecto". Por ejemplo, clúster activado
ID DESC
. Esto a menudo generará el orden inverso (aunque esto tampoco está garantizado).fuente