¿Es mejor estructurar una tabla SQL para que coincida o no devolver ningún resultado?

StackOverflow https://stackoverflow.com/questions/23399

  •  09-06-2019
  •  | 
  •  

Pregunta

Tengo una pregunta de diseño interesante.Estoy diseñando el lado de seguridad de nuestro proyecto, para permitirnos tener diferentes versiones del programa por diferentes costos y también para permitir que los usuarios de tipo Administrador otorguen o denieguen el acceso a partes del programa a otros usuarios.Está basado en la web y alojado en nuestros servidores.

Estoy usando una opción simple de Permitir o Denegar para cada 'Recurso' o pantalla.

Tendremos una gran cantidad de recursos y el usuario podrá configurar muchos grupos diferentes para que los usuarios controlen el acceso.Cada usuario sólo puede pertenecer a un único grupo.

Tengo dos enfoques para esto en mente y tenía curiosidad sobre cuál sería mejor para el servidor SQL en términos de rendimiento.

Opción ALa presencia de una entrada en la tabla de acceso significa que se permite el acceso.Esto no necesitará una columna en la base de datos para almacenar información.Si no se devuelven resultados, se deniega el acceso.

Creo que esto significará una tabla más pequeña, pero ¿las consultas buscarían en toda la tabla para determinar que no hay ninguna coincidencia?

Opción BSe incluye una columna de bits en la base de datos que controla Permitir/Denegar.Esto significará que siempre habrá un resultado que encontrar y creará una tabla más grande.

¿Pensamientos?

¿Fue útil?

Solución

Si solo va a ser Permitir/Denegar, entonces una tabla de vinculación simple entre Usuarios y Recursos funcionaría bien.Si hay una entrada clave para el recurso de usuario en la tabla de vinculación, permita el acceso.

UserResources
-------------
UserId FK->Users
ResourceId FK->Resources

y el sql sería algo así como

if exists (select 1 from UserResources 
where UserId = @uid and ResourceId=@rid)
set @allow=1;

Con un índice agrupado en (UserId y ResourceId), la consulta sería increíblemente rápida incluso con millones de registros.

Otros consejos

Yo votaría por la opción B.Si opta por la opción A y supone que, si existe un usuario, puede ingresar, eventualmente se encontrará con el problema de querer denegar el acceso a un usuario, sin eliminar el registro del usuario.

Habrá muchos casos en los que querrás bloquear a un usuario, pero no destruir completamente su cuenta.Uno de esos casos (no necesariamente vinculado a su caso de uso) es cuando no paga y cortan su cuenta hasta que comienza a pagar nuevamente.No quieren eliminar el registro porque aún quieren habilitarlo cuando vuelva a pagar, en lugar de volver a crear la cuenta desde cero y perder todo el historial del usuario.

B.Permite comprobar mucho mejor si los datos están completos (por ejemplo, cuando agrega una característica permitida/denegada).

Además, el tamaño de la tabla solo debe tenerse en cuenta para las tablas que usted sabe que contendrán muchos registros (como en más de 100.000).Incluso tomarse el tiempo para escribir la consideración del tamaño de la tabla en esta pregunta ya cuesta más que el espacio adicional en el disco duro que ocuparía.

Enfoque A, pero también incluiría una denegación explícita además de la denegación implícita.Haría algunos casos de uso para asegurarme de que su lógica final funcione, pero aquí hay algunos ejemplos.

User1 is in group1 and group2.  
User2 is in group1  
User3 is in group2 

Folder1 allows group1 and deny group2.  
User1 is denied.  
User2 is allowed.  
User3 is denied. 

Creo que su enfoque se permitiría a los usuarios1.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top