2009-11-09 46 views
6

Tôi đã phát hiện ra một vấn đề hiệu suất rất lớn trong LINQ to SQL.LINQ to SQL nvarchar problem

Khi chọn từ bảng bằng chuỗi, thông số được chuyển đến máy chủ sql luôn là nvarchar, ngay cả khi bảng sql là một varchar. Điều này dẫn đến việc quét bảng thay vì tìm kiếm, một vấn đề hiệu suất lớn.

var q = (
    from a in tbl 
    where a.index == "TEST" 
    select a) 

var qa = q.ToArray(); 

Tham số được chuyển qua dưới dạng nvarchar, kết quả trong toàn bộ chỉ mục được chuyển đổi từ varchar sang nvarchar trước khi được sử dụng.

Nếu tham số là một varchar, đó là tìm kiếm rất nhanh.

Có cách nào để ghi đè hoặc thay đổi điều này không?

Cảm ơn Kính trọng Craig.

+0

DBML của bạn trông như thế nào? – RobS

+0

Đó là một cột varchar, không phải là cột nvarchar. tạo thử nghiệm bảng (kiểm tra varchar (200) không null) tạo chỉ mục ixtest trên kiểm tra (thử nghiệm) – Craig

+0

Kế hoạch truy vấn cơ sở dữ liệu sử dụng CONVERT_IMPLICIT và quét thay vì tìm kiếm. Tôi nghĩ rằng đó là một vấn đề LINQ to SQL phổ biến. Tôi đang tìm một giải pháp thay thế cho phép các tham số được chỉ định chính xác. varchar (200) thay vào nvarchar (4) dẫn đến chuyển đổi. – Craig

Trả lời

8

Hmmm. Đây là một lỗi đã biết với các bản dựng trước của RTQ-to-SQL, nhưng từ những gì tôi đọc trực tuyến, đây là một vấn đề cố định cho các so sánh bình đẳng trong RTM (mặc dù vẫn bị hỏng cho các so sánh Contains()).

Bất kể, đây là một chủ đề trên diễn đàn MSDN với một số cách giải quyết chi tiết: http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/4276ecd2-31ff-4cd0-82ea-7a22ce25308b

Cách giải quyết tôi thích nhất là cái này:

//define a query 
IQueryable<Employee> emps = from emp in dc2.Employees where emp.NationalIDNumber == "abc" select emp; 

//get hold of the SQL command translation of the query... 
System.Data.Common.DbCommand command = dc2.GetCommand(emps); 

//change param type from "string" (nvarchar) to "ansistring" (varchar) 
command.Parameters[0].DbType = DbType.AnsiString; 
command.Connection = dc2.Connection; 

//run 
IEnumerable<Employee> emps2 = dc2.Translate<Employee>(command.ExecuteReader()); 

BTW, một trường hợp khác, tôi thấy điều này xảy ra là trong một bảng với phân phối lẻ các giá trị (ví dụ 50% bảng có cùng giá trị) có nghĩa là, khi tham số không được biết đến với SQL Server tại thời gian biên dịch kế hoạch, quét bảng là kế hoạch tốt nhất hiện có. Nếu phân phối của bạn cũng không bình thường, thì cách giải quyết ở trên sẽ không hiệu quả, vì quá trình quét sẽ không đến từ chuyển đổi bị thiếu mà là từ việc tham số hóa chính nó. Trong trường hợp đó, cách giải quyết duy nhất tôi biết sẽ là sử dụng một gợi ý OPTIMIZE FOR và tự xác định SQL.

+0

+1 .. :) đây là một chuỗi msdn khác, cũng có một số giải pháp thay thế khác: http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/20d456f0-9174-4745-bbc5-571f68879e27 – KristoferA

+0

Cảm ơn. Tôi đã nhận ra đó chỉ là vấn đề với chứa. Tôi nghĩ nó rộng hơn lúc đầu. – Craig