Tengo la siguiente vista indizada definida en SQL Server 2008 (puede descargar un esquema de trabajo de GIST para fines de prueba):
CREATE VIEW dbo.balances
WITH SCHEMABINDING
AS
SELECT
user_id
, currency_id
, SUM(transaction_amount) AS balance_amount
, COUNT_BIG(*) AS transaction_count
FROM dbo.transactions
GROUP BY
user_id
, currency_id
;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_balances_user_id_currency_id
ON dbo.balances (
user_id
, currency_id
);
GO
user_id
, currency_id
y transaction_amount
están todos definidos como NOT NULL
columnas en dbo.transactions
. Sin embargo, cuando miro a la definición de la vista en el objeto de estudio de la gerencia Explorer, ambas marcas balance_amount
y transaction_count
como NULL
columnas -able en la vista.
He echado un vistazo a varias discusiones, éste es el más relevante de ellos, que sugieren cierta redistribución de las funciones puede ayudar a SQL Server reconoce que una columna de vista es siempre NOT NULL
. Sin embargo, en este caso no es posible mezclar, ya que las expresiones en funciones agregadas (por ejemplo, un ISNULL()
sobre SUM()
) no están permitidas en las vistas indizadas.
¿Hay alguna manera de que pueda ayudar a SQL Server reconoce que
balance_amount
ytransaction_count
sonNOT NULL
-able?Si no es así, ¿debo preocuparme de que estas columnas se identifiquen erróneamente como
NULL
-able?Las dos preocupaciones que se me ocurren son:
- Los objetos de aplicación asignados a la vista de saldos obtienen una definición incorrecta de un saldo.
- En casos muy limitados, ciertas optimizaciones no están disponibles para el Optimizador de consultas, ya que no tiene una garantía desde el punto de vista de que estas dos columnas lo estén
NOT NULL
.
¿Alguna de estas preocupaciones es un gran problema? ¿Hay alguna otra preocupación que deba tener en cuenta?
fuente
Respuestas:
Me parece que SQL Server tiene una suposición general de que un agregado puede producir
null
incluso si los campos en los que opera sonnot null
. Esto es obviamente cierto en ciertos casos:Y también es cierto en las versiones generalizadas de
group by
likecube
Este caso de prueba más simple ilustra el punto de que cualquier agregado se interpreta como anulable:
En mi opinión, esta es una limitación (aunque menor) de SQL Server: algunos otros RDBMS permiten la creación de ciertas restricciones en las vistas que no se aplican y existen solo para dar pistas al optimizador, aunque creo que es más probable que la 'singularidad' ayuda para generar un buen plan de consulta que 'nulabilidad'
Si la nulabilidad de la columna es importante, tal vez para usar con un ORM, considere ajustar la vista indizada en otra vista que simplemente garantice la no nulabilidad mediante
ISNULL
:fuente
No creo que pueda forzar a SQL Server a reconocer estas columnas como no anulables, aunque claramente no lo son. Puede intentar cambiar el orden de cómo define
ISNULL
/COALESCE
alrededor de la expresión dentroSUM()
, por ejemplo, pero no va a ayudar.Tampoco creo que haya optimizaciones que pueda perderse: esas columnas no están indexadas actualmente, por lo que no es que el optimizador pueda elegir un método de acceso diferente para determinar, por ejemplo, todos los
balance_amount
valores> 10000. Hay puede ser una situación en la que si crea un índice no agrupado en una de esas columnas puede obtener estimaciones ligeramente mejores que si el índice no está allí, pero esto no tiene nada que ver con la nulabilidad.No estaría demasiado preocupado por esto desde una perspectiva de rendimiento. Regresé y miré un montón de vistas indexadas que he creado a lo largo de los años y estas columnas de agregación son anulables. Se desempeñan muy bien.
En cuanto al mapeo de objetos, una vez más, no me preocuparía demasiado. Dado que la aplicación no puede actualizar la vista indizada, no importa si cree que
balance_amount
puede ser asínull
. Nunca va a recibir unnull
, y no puede intentar escribir unnull
, entonces<shrug>
.fuente