2008-12-01 29 views
11

Tôi có một hàng đơn giản mà tôi chỉnh sửa bằng LINQ. Nó có khoảng 30 cột, bao gồm một chuỗi số khóa chính.Chi phí cập nhật 'Phí kiểm tra' cao hơn bao nhiêu cho LINQ UPDATES

Khi một UPDATE được thực hiện thông qua LINQ, câu lệnh UPDATE bao gồm tất cả các cột của bảng (để kiểm tra đồng thời).

Tôi tự hỏi làm thế nào không hiệu quả này là - nếu không negligibiel. Vì có một chỉ mục trên khóa chính, tôi giả định rằng cột đang được sử dụng cho tìm kiếm hàng đầu tiên và sau đó các trường khác đang được kiểm tra ngoài. Tôi sẽ không nghĩ rằng điều này sẽ mất nhiều hơn một lượng thời gian không đáng kể.

Lý do tôi hỏi là tôi đã nhìn thấy UPDATE này mất hơn một giây trong một số trường hợp, mà dường như không có vẻ đúng. Có thể có những hoạt động chạy dài khác đang diễn ra nhưng điều đó khiến tôi tò mò muốn biết liệu tôi có nên lo lắng hay không.

Tôi biết tôi có thể đặt 'UpdateCheck' thành không bao giờ cho tất cả các trường khác, nhưng đây là một nỗi đau.

Có cách nào để tắt 'Cập nhật kiểm tra' cho một SubmitChanges duy nhất() hoặc tôi phải thực hiện việc này bằng cách thay đổi 'UpdateCheck' cho mọi trường.

Mọi lời khuyên sẽ được đánh giá cao.

Dưới đây là bản cập nhật 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 

Trả lời

5

Xác nhận của bạn rằng chi phí cho việc kiểm tra cập nhật là không đáng kể là chính xác. Nếu có một chỉ mục (hoặc khóa chính) được thỏa mãn bởi bất kỳ phần nào của mệnh đề where, thì nó sẽ được sử dụng. Chi phí để kiểm tra các cột khác là không đáng kể. Bạn có thể xác nhận điều này bằng cách cho phép hiển thị kế hoạch thực hiện trong phòng quản lý SQL (hoặc trình phân tích truy vấn cho các phiên bản SQL Server cũ hơn) và chạy bản cập nhật của bạn.

Thời gian thực thi lâu có nhiều khả năng là do cái gì khác. Khóa là một ứng cử viên tốt. Nếu bạn có thể tái tạo nó, hãy sử dụng SQL Profiler để tìm hiểu những gì đang diễn ra.

21

Chúng tôi chạy vào đầu này trên Stack Overflow. Mọi bản cập nhật LINQ to SQL đều xác minh rằng các trường cơ bản chưa thay đổi trước khi viết cập nhật. Nói cách khác, mỗi khi cập nhật được "cập nhật các bản ghi chỉ khi lĩnh vực này tương đương, và lĩnh vực này tương đương, và lĩnh vực này bằng" ..

Chúng tôi quyết định hầu hết thời gian chúng tôi không quan tâm về bản cập nhật bi quan, và trường duy nhất mà bản cập nhật cần kiểm tra là trường Id.

Vì vậy, những gì chúng tôi đã làm được thành lập UpdateCheck="never" cho mọi lĩnh vực ngoại trừ Id trong tập tin bản đồ dbml, như vậy:

<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" /> 

Tôi không biết nếu có một cách để làm điều này lập trình hoặc trên bay.

+0

giải pháp stackoverflowy cho một loại stackoverflowy của vấn đề :-) tôi đã đi với giải pháp dấu thời gian vì tôi không muốn phải thay đổi mỗi cột mỗi khi tôi cập nhật lược đồ –

+0

Có một cách lập trình: Sửa đổi cấu trúc bên trong thông qua phản ánh . Khi mô hình bắt đầu có 100 bảng, điều này có ý nghĩa. – usr

4

Cá nhân, tôi thích sự đơn giản của cột dấu thời gian/hàng phiên bản duy nhất; thiết lập này như cột chỉ để được kiểm tra (IIRC, xảy ra tự động cho timestamp), và bạn đang sắp xếp - sau đó bạn sẽ nhận được TSQL như:

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

này dựa vào họ không được đồng thời (không mâu thuẫn) cập nhật cho cùng một bản ghi; với dấu thời gian/phiên bản hàng v.v., bất kỳ cập nhật xung đột nào sẽ làm cho lần thứ hai bị hủy, ngay cả khi họ cập nhật các cột khác nhau, v.v.

4

Trường thời gian chắc chắn dường như là cách thanh lịch nhất. Tôi ghét phải gây rối với các thuộc tính của từng trường - chủ yếu là vì vậy tôi có thể xóa và thêm lại một cách an toàn một bảng vào tệp DBML của mình mà không phải lo lắng về hậu quả.

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

Các SQL bây giờ tạo ra cho một UPDATE là:

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

và trong cùng một giao dịch:

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 

Nó làm một UPDATE, và sau đó lấy dấu thời gian mới đến gửi lại cho khách hàng của tôi. Tôi không chắc tôi hoàn toàn hiểu những gì @@ ROWCOUNT> 0 có nghĩa là, nhưng ngay bây giờ tôi không thực sự quan tâm :)

+1

@Simon: (@@ ROWCOUNT)> 0) trả về số hàng bị ảnh hưởng từ truy vấn trước đó. Trong trường hợp này, truy vấn của bạn sẽ chỉ trả về dấu thời gian được cập nhật nếu hàng thực sự được cập nhật (nếu không, @ROWCOUNT sẽ bằng 0). Bằng cách này, nếu bạn không nhận được dấu thời gian trong ứng dụng của mình, bạn biết rằng bản cập nhật không thành công. –

+0

Thumbs up cho liên kết! Hoạt động tuyệt vời! – SharpAffair

1

Nếu bạn có thể sửa đổi giản đồ, hãy thêm cột kiểu hàng tuần. LINQ to SQL mới nhất đặt kiểm tra cập nhật thành Không bao giờ cho tất cả các cột. Nếu bạn có một dấu thời gian, nó sẽ sử dụng nó như là một kiểm tra khóa lạc quan, và hệ thống bumps nó mỗi khi có một bản cập nhật.

LƯU Ý: đây là loại dữ liệu Dấu thời gian như được định nghĩa bởi SQL '92, nhưng đã triển khai nó mà không có bất kỳ thông tin thời gian nào để nó không tương thích với bất kỳ hệ thống chuẩn nào khác. Có lẽ đó là cố ý, ai biết được.

+0

có phiên bản 'mới nhất'? .NET 3.5 SP1? tôi đã không nhận thức được rằng –

+0

Tôi tin rằng phiên bản mới nhất được gọi là LINQ to Entities ?? – Jeff

+0

LINQ-to-Sql! = LINQ-to-thực thể –

Các vấn đề liên quan