Tengo un montón de filas que necesito insertar en la tabla, pero estas inserciones siempre se realizan en lotes. Entonces, quiero verificar si existe una sola fila del lote en la tabla porque sé que todas fueron insertadas.
Por lo tanto, no es una verificación de clave principal, pero no debería importar demasiado. Me gustaría verificar solo una fila, por lo que count(*)
probablemente no sea bueno, así exists
que supongo que es algo así .
Pero como soy bastante nuevo en PostgreSQL, prefiero preguntar a las personas que lo saben.
Mi lote contiene filas con la siguiente estructura:
userid | rightid | remaining_count
Entonces, si la tabla contiene alguna fila con siempre userid
, significa que todos están presentes allí.
sql
postgresql
Valentin Kuzub
fuente
fuente
Respuestas:
Use la palabra clave EXISTE para el retorno VERDADERO / FALSO:
fuente
select exists(select 1 from contact where id=12) AS "exists"
exists
olimit 1
tengo una fuerte caída del rendimiento porque Postgres usa Seq Scan en lugar de Index Scan. Yanalyze
no ayuda.¿Qué tal simplemente:
donde
123
está el ID de usuario del lote que está a punto de insertar.La consulta anterior devolverá un conjunto vacío o una sola fila, dependiendo de si hay registros con el ID de usuario dado.
Si esto resulta ser demasiado lento, podría considerar crear un índice
tbl.userid
.Para que esto siga siendo cierto, incluso si su programa se interrumpe a mitad de lote, le recomiendo que se asegure de administrar las transacciones de la base de datos de manera adecuada (es decir, que todo el lote se inserta dentro de una sola transacción).
fuente
COUNT
actos en un anidadoSELECT
que tiene como máximo 1 fila (porqueLIMIT
está en la subconsulta)Por cierto: si desea que todo el lote falle en caso de un duplicado, entonces (dada una restricción de clave principal)
hará exactamente lo que quiere: o tiene éxito o falla.
fuente
Creo que esta es la consulta que utiliza Postgres para verificar las claves externas.
En su caso, también puede hacer esto de una vez:
fuente
como señaló @MikeM.
con índice de contacto, generalmente puede reducir el costo de tiempo a 1 ms.
fuente
Si su conjunto de resultados contiene una fila, entonces no tiene que insertar. De lo contrario, inserte sus registros.
fuente
Si piensa en el rendimiento, puede usar "PERFORM" en una función como esta:
fuente
Me gustaría proponer otro pensamiento para abordar específicamente su oración: "Así que quiero verificar si existe una sola fila del lote en la tabla porque sé que todas fueron insertadas ".
¿Estás haciendo las cosas eficientes insertando en "lotes" pero luego haciendo verificaciones de existencia un registro a la vez? Esto me parece contrario a la intuición. Entonces, cuando dices "las inserciones siempre se hacen en lotes ", entiendo que estás insertando múltiples registros con una declaración de inserción . Debe darse cuenta de que Postgres es compatible con ACID. Si está insertando múltiples registros (un lote de datos) con una declaración de inserción , no es necesario verificar si algunos se insertaron o no. La declaración pasa o fallará. Todos los registros serán insertados o ninguno.
Por otro lado, si su código C # simplemente está haciendo un "conjunto" de instrucciones de inserción separadas, por ejemplo, en un bucle, y en su mente, esto es un "lote" ... entonces, de hecho, no debe describirlo como " las inserciones siempre se realizan en lotes ". El hecho de que espere que parte de lo que llama un "lote" en realidad no se pueda insertar y, por lo tanto, sienta la necesidad de una verificación, sugiere que este es el caso, en cuyo caso tiene un problema más fundamental. Necesita cambiar su paradigma para insertar realmente varios registros con una inserción y renunciar a verificar si los registros individuales lo hicieron.
Considere este ejemplo:
De hecho, este es el paradigma para cualquier DB compatible con ACID ... no solo Postgresql. En otras palabras, estará mejor si arregla su concepto de "lote" y evita tener que hacer verificaciones fila por fila en primer lugar.
fuente