Đối với những người tuyên bố Any() là con đường phía trước tôi đã thực hiện một thử nghiệm đơn giản trong LinqPad so với một cơ sở dữ liệu SQL của CommonPasswords, 14 triệu cho hay lấy. Code:
var password = "qwertyuiop123";
var startTime = DateTime.Now;
"From DB:".Dump();
startTime = DateTime.Now;
if (CommonPasswords.Any(c => System.Data.Linq.SqlClient.SqlMethods.Like(c.Word, password)))
{
$"FOUND: processing time: {(DateTime.Now - startTime).TotalMilliseconds}\r\n".Dump();
}
else
{
$"NOT FOUND: processing time: {(DateTime.Now - startTime).TotalMilliseconds}\r\n".Dump();
}
"From DB:".Dump();
startTime = DateTime.Now;
if (CommonPasswords.Where(c => System.Data.Linq.SqlClient.SqlMethods.Like(c.Word, password)).Count() > 0)
{
$"FOUND: processing time: {(DateTime.Now - startTime).TotalMilliseconds}\r\n".Dump();
}
else
{
$"NOT FOUND: processing time: {(DateTime.Now - startTime).TotalMilliseconds}\r\n".Dump();
}
"From DB:".Dump();
startTime = DateTime.Now;
if (CommonPasswords.Where(c => c.Word.ToLower() == password).Take(1).Any())
{
$"FOUND: processing time: {(DateTime.Now - startTime).TotalMilliseconds}\r\n".Dump();
}
else
{
$"NOT FOUND: processing time: {(DateTime.Now - startTime).TotalMilliseconds}\r\n".Dump();
}
Đây là SQL dịch:
-- Region Parameters
DECLARE @p0 NVarChar(1000) = 'qwertyuiop123'
-- EndRegion
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM [Security].[CommonPasswords] AS [t0]
WHERE [t0].[Word] LIKE @p0
) THEN 1
ELSE 0
END) AS [value]
GO
-- Region Parameters
DECLARE @p0 NVarChar(1000) = 'qwertyuiop123'
-- EndRegion
SELECT COUNT(*) AS [value]
FROM [Security].[CommonPasswords] AS [t0]
WHERE [t0].[Word] LIKE @p0
GO
-- Region Parameters
DECLARE @p0 NVarChar(1000) = 'qwertyuiop123'
-- EndRegion
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT TOP (1) NULL AS [EMPTY]
FROM [Security].[CommonPasswords] AS [t0]
WHERE LOWER([t0].[Word]) = @p0
) AS [t1]
) THEN 1
ELSE 0
END) AS [value]
Bạn có thể thấy rằng bất kỳ kết thúc tốt đẹp các truy vấn lên trong một lớp mã để làm một trường hợp tồn tại sau đó 1 nơi như Count() chỉ cần thêm vào một lệnh Count. Vấn đề với cả hai trong số này là bạn không thể làm một đầu (1) nhưng tôi không thể nhìn thấy một cách tốt hơn sử dụng hàng đầu (1)
Kết quả:
Từ DB: FOUND: thời gian xử lý: 13,3962
Từ DB: FOUND: thời gian xử lý: 12,0933
Từ DB: FOUND: thời gian xử lý: 787,8801
Again:
Từ DB: FOUND: thời gian xử lý: 13,3878
Từ DB: FOUND: thời gian xử lý: 12,6881
Từ DB: FOUND: thời gian xử lý: 780,2686
Again:
Từ DB: FOUND: thời gian xử lý: 24.7081
Từ DB: FOUND: thời gian xử lý: 23,6654
Từ DB: FOUND: thời gian xử lý: 699,622
Without Index:
Từ DB: FOUND: thời gian xử lý: 2395.1988
Từ DB: FOUND: thời gian xử lý: 390,6334
Từ DB: FOUND: thời gian xử lý: 664,8581
Bây giờ một số bạn có thể nghĩ nó chỉ là một hoặc hai phần nghìn giây. Tuy nhiên, sự chênh lệch lớn hơn nhiều trước khi tôi đặt chỉ mục lên đó; một vài giây.
Tính toán cuối cùng là khi tôi bắt đầu với khái niệm ToLower() sẽ nhanh hơn LIKE, và tôi đã đúng, cho đến khi tôi thử đếm và đặt chỉ mục trên đó. Tôi đoán Lower() làm cho chỉ mục không liên quan.
Bổ sung thêm cho bạn chỉ vì tôi chưa bao giờ nhận ra có tính năng ghi nhật ký SQL cho LINQ to Sql. Tôi đã phải chạy SQL Profiler toàn bộ thời gian này. – David
@ David - thực sự. Tôi tiếp tục yêu cầu nhóm dữ liệu MS thêm nó cho EF ;-p –
nếu bạn muốn ** sử dụng Người dùng sau đó ** thay vì viết một truy vấn thứ hai vào cơ sở dữ liệu thì sao? kiểm tra [this] (http://stackoverflow.com/a/1071063/2218697), hy vọng sẽ giúp ai đó. – stom