5

En mi aplicación actual Rails, estoy resolviendo conflictos de programación ordenando los modelos por el campo "created_at". Sin embargo, me di cuenta de que al insertar varios modelos de un formulario que permite esto, todas las veces created_at son exactamente las mismas.¿Se puede confiar en la clave primaria de incremento automático en su base de datos?

Esto es más una cuestión de mejores prácticas de programación: ¿Puede su aplicación confiar en su columna de ID en su base de datos para incrementar cada vez más con cada INSERT para obtener su orden de creación? Para decirlo de otra manera, ¿puedo ordenar un grupo de filas que saque de mi base de datos por su columna de ID y estar seguro de que este es un tipo preciso basado en el orden de creación? ¿Y esta es una buena práctica en mi aplicación?

Respuesta

1

Eso depende de su proveedor de la base de datos.

MySQL Creo que ordena absolutamente las teclas de incremento automático. SQL Server No estoy seguro de que lo haga o no, pero creo que sí.

Donde se encontrará con problemas es con bases de datos que no son compatibles con esta funcionalidad, sobre todo Oracle que utiliza secuencias, que son más o menos ordenadas.

Una alternativa podría ser ir para el tiempo creado y luego ID.

+0

Me gusta la idea de redundancia, ordenar por uno y luego usar ID para un tipo secundario. . . ¡Gracias! – BushyMark

+0

Las secuencias de Oracle se ordenan para instalaciones que no son de RAC, que son la gran mayoría de ellas. –

2

Los números de identificación generados serán únicos. Independientemente de si usa Secuencias, como en PostgreSQL y Oracle o si usa otro mecanismo como el auto-incremento de MySQL.

Sin embargo, las secuencias se adquieren con mayor frecuencia en granel de, por ejemplo, 20 números. Así que con PostgreSQL no puede determinar qué campo se insertó primero. Incluso podría haber lagunas en la identificación de los registros insertados.

Por lo tanto, no debe usar un campo de ID generado para una tarea como esa para no confiar en los detalles de implementación de la base de datos.

Generación de un campo actualizadocreado o durante la ejecución del comando es mucho mejor para la clasificación por creación-, o la actualización más adelante. Por ejemplo:

INSERT INTO A (data, created) VALUES (smething, DATE()) 
UPDATE A SET data=something, updated=DATE() 
0

Creo que la respuesta a su pregunta es sí ... si leo entre líneas, creo que le preocupa que el sistema puede volver a utilizar los números de identificación que han 'desaparecido' en la secuencia, y por lo tanto, si hubiera usado 1,2,3,5,6,7 como números de identificación, en todas las implementaciones que conozco, el próximo número de identificación siempre será 8 (o posiblemente más), pero no lo hago Conozco cualquier DB que intente averiguar que falta la Id. de registro # 4, así que intente volver a utilizar ese número de ID.

Aunque estoy muy familiarizado con SQL Server, no sé por qué cualquier proveedor que intente llenar los vacíos en una secuencia: piense en la sobrecarga de mantener esa lista de ID no utilizados, en lugar de simplemente mantener el seguimiento del último número que utilicé, y agregando 1.

Diría que puede confiar en que el próximo número de ID asignado siempre será más alto que el anterior, no solo único.

0

Sí, la identificación será única y no, no puede y no debe confiar en ella para la clasificación, está ahí para garantizar la exclusividad de la fila solamente. El mejor enfoque es, como lo indican las emktas, usar un campo separado "actualizado" o "creado" solo para esta información.

Para ajustar el tiempo de creación, sólo puede utilizar un valor predeterminado como esto

CREATE TABLE foo (
    id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL; 
    created TIMESTAMP NOT NULL DEFAULT NOW(); 
    updated TIMESTAMP; 
    PRIMARY KEY(id); 
) engine=InnoDB; ## whatever :P 

Ahora, que se encarga de la creación. con el tiempo de actualización sugeriría un UPDATE desencadenador AFTER como éste (por supuesto, puede hacerlo de una consulta independiente, pero el gatillo, en mi opinión, es una mejor solución - más transparente):

DELIMITER $$ 
CREATE TRIGGER foo_a_upd AFTER UPDATE ON foo 
FOR EACH ROW BEGIN 
    SET NEW.updated = NOW(); 
END; 
$$ 
DELIMITER ; 

Y Deberias hacer eso.

EDITAR: Woe is me. Tontamente no he especificado, que esto es para mysql, podría haber algunas diferencias en los nombres de las funciones (es decir, 'AHORA') y otras sutiles itty-bitty.

+1

Está ignorando lo que dijo el OP: ya tiene un campo created_at y que es lo mismo cuando se insertan varios elementos al mismo tiempo, de ahí su pregunta. – cletus

+0

Parece, de hecho, que mi línea de pensamiento, desviándose violentamente como es, se ha desviado hacia una vía lateral. Lo siento. Usted tiene, por supuesto, razón. Ordenar primero por created_at y luego por id es, probablemente, la solución más fácil (aunque probablemente no garantice estrictamente el orden correcto, solo garantiza que las filas con los mismos valores de created_at se devolverán en el mismo orden cada una) hora). – shylent

0

Una advertencia a la respuesta de EJB:

SQL no da ninguna garantía de ordenar si no se especifica una orden por la columna. P.ej. si elimina algunas filas iniciales y luego las inserta, las nuevas pueden terminar viviendo en el mismo lugar en el db que las antiguas (aunque con nuevas identificaciones), y eso es lo que puede usar como su clasificación predeterminada.

FWIW, normalmente utilizo el pedido por ID como una versión efectiva del pedido creado por. Es más económico porque no requiere agregar un índice a un campo de fecha y hora (que es más grande y, por lo tanto, más lento que un índice de clave primaria entera simple), se garantiza que será diferente, y realmente no me importa si algunas filas fueron agregado aproximadamente al mismo tiempo, ordena en un orden ligeramente diferente.

0

Probablemente este motor de DB dependa. Verificaría cómo su base de datos implementa secuencias y si no hay problemas documentados, entonces decidiría confiar en la identificación.

E.g. Postgresql sequence está bien, a menos que juegues con los parámetros de la caché de secuencia.

Existe la posibilidad de que otro programador cree o copie manualmente registros de diferentes bases de datos con una columna de ID incorrecta. Sin embargo, simplificaría el problema. No se moleste con casos de baja probabilidad donde alguien destruirá manualmente la integridad de los datos. No puedes proteger contra todo.

Mi consejo es confiar en las identidades generadas secuencia y mover su proyecto hacia adelante.

0

En teoría, sí, el número de identificación más alto es el último creado. Sin embargo, recuerde que las bases de datos tienen la capacidad de desactivar temporalmente la inserción del valor autogenerado, insertar algunos registros de forma manua y luego volverlos a activar. Estas inserciones no se utilizan normalmente en un sistema de producción, pero pueden ocurrir ocasionalmente cuando se mueve una gran cantidad de datos de otro sistema.

Cuestiones relacionadas