update latest last cumulative sql-server linq updatecheck

sql server - latest - ¿Cuánta sobrecarga tiene ''Update Check'' para LINQ UPDATES?



sql server 2017 updates (5)

Tengo una fila simple que edito usando LINQ. Tiene alrededor de 30 columnas, incluida una secuencia numérica de tecla principal.

Cuando se realiza una ACTUALIZACIÓN a través de LINQ, la instrucción UPDATE incluye todas las columnas de la tabla (para la comprobación de concurrencia).

Me pregunto qué tan ineficiente es esto, si no es negligibiel. Dado que hay un índice en la clave principal, supongo que la columna se está utilizando para la búsqueda de fila inicial y, a continuación, los demás campos se están verificando además. No hubiera pensado que esto tomaría más que una cantidad insignificante de tiempo.

La razón por la que pregunto es que he visto que esta ACTUALIZACIÓN toma más de un segundo en algunos casos, lo que simplemente no parece correcto. Puede haber otras operaciones de larga duración, pero me hizo sentir curiosidad por si debería preocuparme o no.

Sé que puedo configurar ''UpdateCheck'' para nunca para todos los demás campos, pero esto es un problema.

¿Hay alguna manera de desactivar ''Actualizar verificación'' para un solo SubmitChanges (), o tengo que hacerlo cambiando ''UpdateCheck'' para cada campo.

Cualquier consejo sería apreciado.

Aquí está la actualización de SQL:

exec sp_executesql N''UPDATE [dbo].[SiteVisit] SET [TotalTimeOnSite] = @p12, [ContentActivatedTime] = @p13 WHERE ([SiteVisitId] = @p0) AND ([SiteUserId] IS NULL) AND ([ClientGUID] = @p1) AND ([ServerGUID] IS NULL) AND ([UserGUID] = @p2) AND ([SiteId] = @p3) AND ([EntryURL] = @p4) AND ([CampaignId] = @p5) AND ([Date] = @p6) AND ([Cookie] IS NULL) AND ([UserAgent] = @p7) AND ([Platform] IS NULL) AND ([Referer] = @p8) AND ([KnownRefererId] = @p9) AND ([FlashVersion] IS NULL) AND ([SiteURL] IS NULL) AND ([Email] IS NULL) AND ([FlexSWZVersion] IS NULL) AND ([HostAddress] IS NULL) AND ([HostName] IS NULL) AND ([InitialStageSize] IS NULL) AND ([OrderId] IS NULL) AND ([ScreenResolution] IS NULL) AND ([TotalTimeOnSite] IS NULL) AND ([CumulativeVisitCount] = @p10) AND ([ContentActivatedTime] IS NULL) AND ([ContentCompleteTime] IS NULL) AND ([MasterVersion] = @p11) AND ([VisitedHome] IS NULL) AND ([VisitedStore] IS NULL) AND ([VisitedVideoDemos] IS NULL) AND ([VisitedProducts] IS NULL) AND ([VisitedAdvantages] IS NULL) AND ([VisitedGallery] IS NULL) AND ([VisitedTestimonials] IS NULL) AND ([VisitedEvolution] IS NULL) AND ([VisitedFAQ] IS NULL)'',N''@p0 int,@p1 uniqueidentifier,@p2 uniqueidentifier,@p3 int,@p4 varchar(46),@p5 varchar(3),@p6 datetime,@p7 varchar(164),@p8 varchar(36),@p9 int,@p10 int,@p11 int,@p12 int,@p13 int'',@p0=1009772,@p1=''039A0614-31EE-4DD9-9E1A-8A0F947E1719'',@p2=''C83C0E68-142A-47CB-B7F9-BAF462E79429'',@p3=1,@p4=''http://www.example.com/default.aspx?c=183'',@p5=''183'',@p6=''2008-11-30 18:22:59:047'',@p7=''Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SIMBAR={85B62341-3F6B-4645-A473-53A2D2BB66DC}; FunWebProducts; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727)'',@p8=''http://apps.facebook.com/inthemafia/'',@p9=1,@p10=1,@p11=30,@p12=6,@p13=6


El campo de marca de tiempo ciertamente parecía ser la manera más elegante de hacer esto. ME ODIO tener que meterme con las propiedades de los campos individuales, principalmente para poder eliminar y volver a agregar de forma segura una tabla a mi archivo DBML sin tener que preocuparme por las consecuencias.

http://msdn.microsoft.com/en-us/library/bb470449.aspx

El SQL ahora generado para una ACTUALIZACIÓN es:

exec sp_executesql N''UPDATE [dbo].[SiteVisit] SET [TotalTimeOnSite] = @p2 WHERE ([SiteVisitId] = @p0) AND ([timestamp] = @p1)

y en la misma transacción:

SELECT [t1].[timestamp] FROM [dbo].[SiteVisit] AS [t1] WHERE ((@@ROWCOUNT) > 0) AND ([t1].[SiteVisitId] = @p3)'',N''@p0 int,@p1 timestamp,@p2 int,@p3 int'',@p0=814109,@p1=0x0000000000269CB8,@p2=1199920,@p3=814109

Hace una ACTUALIZACIÓN, y luego recupera la nueva marca de tiempo para enviar de vuelta a mi cliente. No estoy seguro de entender completamente lo que significa @@ ROWCOUNT> 0, pero en este momento no me importa :)


Su afirmación de que la sobrecarga de la verificación de actualización es insignificante es correcta. Si hay un índice (o clave principal) que satisface cualquier parte de la cláusula where, entonces se usará. El costo de verificar las otras columnas es insignificante. Puede confirmar esto habilitando la visualización del plan de ejecución en SQL Management Studio (o el analizador de consultas para versiones anteriores de SQL Server) y ejecute su actualización.

Los tiempos de ejecución largos probablemente se deben a algo más. Locking es un buen candidato. Si puede reproducirlo, use el Analizador de SQL para descubrir qué está sucediendo.


Nos encontramos con esto temprano en . Cada actualización LINQ to SQL verifica que los campos subyacentes no hayan cambiado antes de escribir una actualización. En otras palabras, cada actualización es "actualizar el registro solo si este campo es igual, y este campo es igual a, y este campo es igual a" ...

Decidimos la mayor parte del tiempo que no nos importaban las actualizaciones pesimistas, y el único campo que la actualización debe verificar es el campo Id.

Entonces, lo que hicimos fue establecer UpdateCheck="never" para cada campo excepto el Id en el archivo de mapeo dbml, así:

<Type Name="Badge"> <Column Name="Id" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" /> <Column Name="Class" Type="System.Byte" DbType="TinyInt NOT NULL" CanBeNull="false" UpdateCheck="Never" /> <Column Name="Name" Type="System.String" DbType="VarChar(50) NOT NULL" CanBeNull="false" UpdateCheck="Never" />

No sé si hay una manera de hacer esto programáticamente o sobre la marcha.


Personalmente, me gusta la simplicidad de una sola columna timestamp / row-version; establezca esto como la única columna que se comprobará (IIRC, se produce automáticamente para la timestamp de timestamp ), y está ordenado; a continuación, debe obtener TSQL como:

exec sp_executesql N''UPDATE [dbo].[SiteVisit] SET [TotalTimeOnSite] = @p2, [ContentActivatedTime] = @p3 WHERE ([SiteVisitId] = @p0) AND ([Timestamp] = @p1)

Esto se basa en que no son actualizaciones concurrentes (no conflictivas) del mismo registro; con una marca de tiempo / versión de fila, etc., cualquier actualización conflictiva hará que la segunda aborte, incluso si actualizaron columnas diferentes, etc.


Si puede modificar el esquema, agregue una columna de tipo rowversion. El último LINQ to SQL establece la comprobación de actualización en Nunca para todas las columnas. Si tiene una marca de tiempo, la usará como una verificación de bloqueo optimista, y el sistema la golpea cada vez que hay una actualización.

NOTA: este solía ser el tipo de datos Timestamp tal como lo definió SQL ''92, pero lo implementó sin ninguna información de tiempo, por lo que no era compatible con ningún otro sistema estándar. Tal vez fue intencional, quién sabe.