Escenario: SQL Server 2014 (v12.0.4100.1)
.NET Service ejecuta esta consulta:
SELECT name, base_object_name
FROM sys.synonyms
WHERE schema_id IN (SELECT schema_id
FROM sys.schemas
WHERE name = N'XXXX')
ORDER BY name
... que devuelve alrededor de 6500 filas pero a menudo se agota después de más de 3 minutos. Lo XXXX
anterior no es 'dbo'.
Si ejecuto esta consulta en SSMS como UsuarioA, la consulta vuelve en menos de un segundo.
Cuando se ejecuta como UserB (que es cómo se conecta el servicio .NET), la consulta demora de 3 a 6 minutos y tiene el% de CPU al 25% (de 4 núcleos) todo el tiempo.
UserA es un inicio de sesión de dominio en el rol sysadmin
UserB es un inicio de sesión SQL con:
EXEC sp_addrolemember N'db_datareader', N'UserB'
EXEC sp_addrolemember N'db_datawriter', N'UserB'
EXEC sp_addrolemember N'db_ddladmin', N'UserB'
GRANT EXECUTE TO [UserB]
GRANT CREATE SCHEMA TO [UserB]
GRANT VIEW DEFINITION TO [UserB]
Puedo duplicar esto en SSMS envolviendo el SQL anterior en un Execute as...Revert
bloque, por lo que el código .NET está fuera de la imagen.
El plan de ejecución se ve igual. Difundí el XML y solo hay pequeñas diferencias (CompileTime, CompileCPU, CompileMemory).
Todas las estadísticas de IO no muestran lecturas físicas:
Tabla 'sysobjvalues'. Cuenta de escaneo 0, lecturas lógicas 19970, lecturas físicas 0, lecturas de lectura anticipada 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas de lectura lob 0. Tabla 'Archivo de trabajo'. Recuento de exploración 0, lecturas lógicas 0, lecturas físicas 0, lecturas de lectura anticipada 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas de lectura lob 0. Mesa 'Mesa de trabajo'. Recuento de exploración 0, lecturas lógicas 0, lecturas físicas 0, lecturas de lectura anticipada 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas de lectura lob 0. Tabla 'sysschobjs'. Cuenta de escaneo 1, lecturas lógicas 9122, lecturas físicas 0, lecturas de lectura anticipada 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas de lectura lob 0. Tabla 'sysclsobjs'. Cuenta de escaneo 0, lecturas lógicas 2, lecturas físicas 0, lecturas de lectura anticipada 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas lob de lectura anticipada 0.
Los estados de espera de XEvent (para una consulta de ~ 3 minutos) son:
+ --------------------- + ------------ + -------------- -------- + ------------------------------ + ---------- ------------------- + El | Esperar tipo | Espera cuenta | Tiempo de espera total (ms) | Tiempo total de espera de recursos (ms) | Tiempo de espera de señal total (ms) | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- + El | SOS_SCHEDULER_YIELD | 37300 | 427 20 | 407 El | NETWORK_IO | 5 | 26 | 26 | 0 | El | IO_COMPLETION | 3 | 1 | 1 | 0 | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- +
Si reescribo la consulta (en SSMS, no tengo acceso al Código de la aplicación) para
declare @id int
SELECT @id=schema_id FROM sys.schemas WHERE name = N'XXXX'
SELECT a.name, base_object_name FROM sys.synonyms a
WHERE schema_id = @id
ORDER BY name
entonces UserB se ejecuta a la misma velocidad (rápida) que UserA.
Si agrego db_owner
al usuario B, entonces, nuevamente, la consulta se ejecuta <1 seg.
Esquema creado a través de esta plantilla:
DECLARE @TranName VARCHAR(20)
SELECT @TranName = 'MyTransaction'
BEGIN TRANSACTION @TranName
GO
IF NOT EXISTS (SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = '{1}')
BEGIN
EXEC('CREATE SCHEMA [{1}]')
EXEC sp_addextendedproperty @name='User', @value='{0}', @level0type=N'Schema', @level0name=N'{1}'
END
GO
{2}
COMMIT TRANSACTION MyTransaction;
GO
Y creo que {2} es una lista de sinónimos creados en ese esquema.
Perfil de consulta en dos puntos de la consulta:
Abrí un boleto con Microsoft.
Además, intentamos agregar UserB a db_owner
, y luego incorporar DENY
todos los privilegios con los que sabemos que están asociados db_owner
. El resultado es una consulta rápida. O nos perdimos algo (completamente posible), o hay una verificación especial para el db_owner
papel.
access check cache bucket count
yaccess check cache quota
las opciones de configuración previamente. Tendrá que jugar un poco con ellos.WHILE(1=1) BEGIN DBCC FREESYSTEMCACHE ('TokenAndPermUserStore') WAITFOR DELAY '00:00:05' END
un bucle para siempre, la consulta se completa en menos de 2 minutos frente a 8 minutos normalmente.Si esto todavía está en vivo, hemos tenido el mismo problema, parece que si usted es el dbo o un administrador de sistemas, entonces cualquier acceso a sys.objects (o algo así), entonces es instantáneo sin controles contra objetos individuales.
si es un db_datareader humilde, entonces tiene que verificar cada objeto a su vez ... está oculto en el plan de consulta ya que estos se comportan más como funciones que vistas / tablas
el plan se ve igual, pero está haciendo cosas diferentes detrás del capó
fuente
El uso del indicador de seguimiento 9481 parece resolver este problema para mí.
El CE (Estimador de cardinalidad) en 2014 (compat 120) cambió de 2012 y 2008, y el uso de TF 9481 fuerza el uso del CE de 2012.
Consulte El estimador de cardinalidad SQL 2014 come TSQL incorrecto para el desayuno de Kendra Little.
fuente