성능이 더 좋은 방법은 무엇입니까: .숫자() 대 숫자() > 0?
에 시대에System.Linq
네임스페이스. 이제 IEnumber를 Any() 및 Count() 확장 메서드로 확장할 수 있습니다.
에 하나 이 포함되어 ▁the▁iion다▁▁inside▁use▁▁should습▁that▁recently▁that▁i▁collect었▁told▁i▁1▁was최▁it▁a고한▁or근▁check다▁want,▁to▁items사를 사용해야 한다고 들었습니다..Any()
대신 확장 .Count() > 0
는 장방법다같때기문다니입음과확은▁the▁because▁extension▁method다니때문입같..Count()
확장 메서드는 모든 항목을 반복해야 합니다.
두 번째로, 일부 컬렉션은 (확장 방법이 아닌) 다음과 같은 속성을 가집니다.Count
또는Length
그것들을 사용하는 것이 더 나을까요, 대신에..Any()
또는.Count()
?
네 / 네?
만약 당신이 무언가를 가지고 시작한다면,.Length
또는.Count
예:ICollection<T>
,IList<T>
,List<T>
etc) - 그러면 이것이 가장 빠른 옵션이 될 것입니다, 왜냐하면 그것은 그것이 통과할 필요가 없기 때문입니다.GetEnumerator()
/MoveNext()
/Dispose()
가 하는 순서Any()
비어 있지 않은 것을 확인합니다IEnumerable<T>
순서.
ㅠㅠIEnumerable<T>
,그리고나서Any()
한 번의 반복만 보면 되므로 일반적으로 더 빠릅니다.그러나 LINQ-to-Objects의 구현은 다음과 같습니다.Count()
합니다.ICollection<T>
((으)로 사용.Count
최적화) - 기본 데이터 소스가 직접 목록/수집인 경우 큰 차이가 없습니다.일반이 아닌 것을 사용하지 않는 이유를 묻지 마십시오.ICollection
...
등을 수행한 (LINQ의 경우)Where
등), 반복기-블록 기반 시퀀스가 있을 것이며, 따라서 다음과 같습니다.ICollection<T>
최적화는 쓸모가 없습니다.
으로 일적으로와 .IEnumerable<T>
▁▁stick을다.Any()
;-p
참고: 기업 프레임워크 4가 실제일 때 이 답변을 작성했습니다.이 대답의 요점은 사소한 일에 끼어들지 않는 것이었습니다..Any()
대.Count()
가 멀다는 이었습니다.요점은 EF가 완벽과는 거리가 멀다는 것을 알리는 것이었습니다.새버 더좋다습니이전비를오... 하지만 하지 말고 하지만코일느드부리가로경사고용직는하시우십하성 TSQL교을능접에는트스하고테의ance▁rather▁perform▁butql▁thatthat▁test오비▁(십ptions▁tsql시▁if▁compare하교▁with▁of새▁you▁ef,▁and을능▁code전...▁and▁direct성▁relying▁than▁it)..Any()
항상보빠다니릅다다▁than▁always니▁is보다 빠릅니다..Count() > 0
).
논평에 하지만, 이 는 동의합니다.Any
보다 나은 개발자 의도 신호Count() > 0
SQL Server(Entity Framework 4)에서 Count를 지정합니다.
다음과 같은 질문이 있습니다.Any
제한 시간 예외(최대 200.000개 레코드):
con = db.Contacts.
Where(a => a.CompanyId == companyId && a.ContactStatusId <= (int) Const.ContactStatusEnum.Reactivated
&& !a.NewsletterLogs.Any(b => b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr)
).OrderBy(a => a.ContactId).
Skip(position - 1).
Take(1).FirstOrDefault();
Count
밀리초 내에 실행된 버전:
con = db.Contacts.
Where(a => a.CompanyId == companyId && a.ContactStatusId <= (int) Const.ContactStatusEnum.Reactivated
&& a.NewsletterLogs.Count(b => b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr) == 0
).OrderBy(a => a.ContactId).
Skip(position - 1).
Take(1).FirstOrDefault();
을 생성하는, 사이에 성능 가 큰 것은합니다. 하지만 성능 차이가 매우 큽니다.Count
그리고.Any
어떤 경우에는, 그리고 불행하게도 당신은 그냥 있을 수 없는 것처럼 보입니다.Any
어떤 경우에도
편집: 생성된 SQL입니다.보다시피 아름다운 것들 ;)
ANY
:
exec sp_executesql N'SELECT TOP (1)[프로젝트 2].[ContactId] AS [ContactId],[프로젝트 2].[CompanyId] AS [CompanyId],[프로젝트 2].[ContactName] AS [ContactName],[프로젝트 2].[FullName] AS [FullName],[프로젝트 2].[ContactStatusId] AS [ContactStatusId],[프로젝트 2].[작성] AS [작성]FROM([Project2] 선택).[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[작성됨] AS [작성됨], row_number() OVER([프로젝트2]별 주문).[ContactId] ASC) AS [row_number]시작(선택)[범위1][ContactId] AS [ContactId],[범위1][CompanyId] AS [CompanyId],[범위1][ContactName] AS [ContactName],[범위1][FullName] AS [FullName],[범위1][ContactStatusId] AS [ContactStatusId],[범위1][작성] AS [작성]출처 [dbo].[연락처] AS [내재1]WHERE([Extent1]).[CompanyId] = @p__linq__0) 및 ([Extent1].[ContactStatusId] <= 3) 및 (존재하지 않음(선택)1 AS [C1]출처 [dbo].[뉴스레터로그] AS [Extent2]WHERE([Extent1]).[ContactId] = [Extent2].[ContactId])AND(6 = [Extent2]).[뉴스레터 LogTypeId]))) AS [프로젝트2]) AS [프로젝트2]WHERE [프로젝트 2].[row_number] >[프로젝트 2]에 따라 주문합니다.[ContactId] ASC',N'@p__linq_0 int',@p__linq_0=4
COUNT
:
exec sp_executesql N'SELECT TOP (1)[프로젝트 2].[ContactId] AS [ContactId],[프로젝트 2].[CompanyId] AS [CompanyId],[프로젝트 2].[ContactName] AS [ContactName],[프로젝트 2].[FullName] AS [FullName],[프로젝트 2].[ContactStatusId] AS [ContactStatusId],[프로젝트 2].[작성] AS [작성]FROM([Project2] 선택).[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[작성됨] AS [작성됨], row_number() OVER([프로젝트2]별 주문).[ContactId] ASC) AS [row_number]시작(선택)[프로젝트 1].[ContactId] AS [ContactId],[프로젝트 1].[CompanyId] AS [CompanyId],[프로젝트 1].[ContactName] AS [ContactName],[프로젝트 1].[FullName] AS [FullName],[프로젝트 1].[ContactStatusId] AS [ContactStatusId],[프로젝트 1].[작성] AS [작성]시작(선택)[범위1][ContactId] AS [ContactId],[범위1][CompanyId] AS [CompanyId],[범위1][ContactName] AS [ContactName],[범위1][FullName] AS [FullName],[범위1][ContactStatusId] AS [ContactStatusId],[범위1][작성] AS [작성],(선택)카운트(1) AS [A1]출처 [dbo].[뉴스레터로그] AS [Extent2]WHERE([Extent1]).[ContactId] = [Extent2].[ContactId])AND(6 = [Extent2]).[뉴스레터 LogTypeId]) AS [C1]출처 [dbo].[연락처] AS [내재1]) AS [Project1]WHERE([프로젝트1]).[CompanyId] = @p__linq__0) AND ([Project1]).[ContactStatusId] <= 3) AND (0 = [Project1].[C1])) AS [프로젝트2]) AS [프로젝트2]WHERE [프로젝트 2].[row_number] >[프로젝트 2]에 따라 주문합니다.[ContactId] ASC',N'@p__linq_0 int',@p__linq_0=4
카운트를 계산한 다음 카운트를 사용하여 Where == 0을 수행하는 것보다 Pure Where with EXISTS가 훨씬 더 잘 작동하지 않는 것 같습니다.
제 연구 결과에 오류가 있으면 알려주세요.Any vs Count 논의와 상관없이 이 모든 것에서 얻을 수 있는 것은 저장 프로시저 ;)로 다시 작성하면 더 복잡한 LINQ가 훨씬 낫다는 것입니다.
정확한 세부 정보는 에서 약간 다릅니다. Framework 대NET Core를NET Core사경우는는다에작따다다릅니소라내용에업하용▁you▁it▁net▁but▁▁if':▁다▁somewhat▁an대▁on.ICollection
또는ICollection<T>
: 이핑예사용을타예)List<T>
..Count
다른 유형의 경우 열거형이 필요할 수 있는 반면, 액세스 비용이 저렴한 속성입니다.
TL;DR:
사용하다.Count > 0
존재하고 속이존는경우, 또그않경은우지렇는..Any()
.
용사를 합니다..Count() > 0
결코 최상의 옵션이 아니며, 경우에 따라 속도가 크게 느려질 수 있습니다.
이는 두 가지 모두에 적용됩니다.NET Framework 및 .NET 코어.
이제 세부 사항을 자세히 살펴보도록 하겠습니다.
목록 및 컬렉션
가장 일반적인 사례로 시작하겠습니다. 사용List<T>
( (으)로 표시됩니다ICollection<T>
).
그.Count
속성은 다음과 같이 구현됩니다.
private int _size;
public int Count {
get {
Contract.Ensures(Contract.Result<int>() >= 0);
return _size;
}
}
것은 이이말는것입다니하것다것니입니다._size
는 에의유니다됩에 의해 됩니다.Add()
,Remove()
등, 그리고 그것은 단지 필드에 접근하는 것이기 때문에, 이것은 매우 저렴한 작업입니다. 우리는 가치에 대해 반복할 필요가 없습니다.
ICollection
그리고.ICollection<T>
둘 다 가지고 있습니다.Count
그리고 이를 구현하는 대부분의 유형은 유사한 방식으로 그렇게 할 가능성이 높습니다.
기타 IE 숫자
타IEnumerable
한그않유형은이 아닌 유형ICollection
비어 있는지 확인하려면 열거를 시작해야 합니다.성능에 영향을 미치는 주요 요인은 단일 항목(이상적인) 또는 전체 컬렉션(상대적으로 비싼)을 열거하는 것입니다.
데이터베이스나 디스크에서 읽는 것과 같이 실제로 수집으로 인해 I/O가 발생하는 경우 성능이 크게 저하될 수 있습니다.
. Framework.NET 프레임워크.Any()
. Framework에서는 .NET 프레임워크(4.8)Any()
구현:
public static bool Any<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return true;
}
return false;
}
즉, 새 열거자 개체를 가져와 한 번 반복해 봅니다.이것은 전화하는 것보다 더 비쌉니다.List<T>.Count
적어도 전체 목록을 반복하는 것은 아닙니다.
. Framework.NET 프레임워크.Count()
. Framework에서는 .NET 프레임워크(4.8)Count()
구현은 다음과 같습니다(계속)
public static int Count<TSource>(this IEnumerable<TSource> source)
{
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null)
{
return collection.Count;
}
int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
num = checked(num + 1);
}
return num;
}
}
경우, 한경우가능ICollection.Count
사용되지만 그렇지 않으면 컬렉션이 열거됩니다.
. Core.NET 코어.Any()
LINQAny()
…에서의 실시NET Core가 훨씬 더 똑똑합니다.여기에서 전체 소스를 볼 수 있지만 이 토론과 관련된 비트는 다음과 같습니다.
public static bool Any<TSource>(this IEnumerable<TSource> source)
{
//..snip..
if (source is ICollection<TSource> collectionoft)
{
return collectionoft.Count != 0;
}
//..snip..
using (IEnumerator<TSource> e = source.GetEnumerator())
{
return e.MoveNext();
}
}
냐하면.List<T>
입니다.ICollection<T>
이것은 그것을 부를 것입니다.Count
속성(및 다른 메서드를 호출하지만 추가 할당은 없습니다.)
. Core.NET 코어.Count()
.NET Core 구현(소스)은 기본적으로 와 동일합니다.NET Framework(위 참조)를 사용합니다.ICollection.Count
사용 가능한 경우 컬렉션을 열거합니다.
요약
.NET 프레임워크
와 함께
ICollection
:.Count > 0
ㅜㅜㅜㅜ.Count() > 0
괜찮아요, 하지만 궁극적으로는 그냥 전화만 해요.ICollection.Count
.Any()
.
가 아닌 경우 경
ICollection
(아니오.Count
속성).Any()
좋습니다..Count() > 0
입니다.
.NET 코어
.Count > 0
가능한 좋습니다 가능한 경우).ICollection
).Any()
괜찮아요, 그리고 둘 중 하나가 될 거예요.ICollection.Count > 0
단일 합니다..Count() > 0
입니다.
이것은 꽤 인기 있는 주제이고 답이 다르기 때문에, 저는 그 문제에 대해 새롭게 살펴봐야 했습니다.
테스트 환경: EF 6.1.3, SQL 서버, 300k 레코드
테이블 모델:
class TestTable
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
테스트 코드:
class Program
{
static void Main()
{
using (var context = new TestContext())
{
context.Database.Log = Console.WriteLine;
context.TestTables.Where(x => x.Surname.Contains("Surname")).Any(x => x.Id > 1000);
context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Any(x => x.Id > 1000);
context.TestTables.Where(x => x.Surname.Contains("Surname")).Count(x => x.Id > 1000);
context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Count(x => x.Id > 1000);
Console.ReadLine();
}
}
}
결과:
임의() ~ 3ms
Count() - 첫 번째 쿼리의 경우 230ms, 두 번째 쿼리의 경우 400ms
비고:
저의 경우, EF는 그의 게시물에 언급된 @Ben과 같은 SQL을 생성하지 않았습니다.
EDIT: EF 버전 6.1.1에서 수정되었으며 이 답변은 더 이상 실제가 아닙니다.
SQL Server 및 EF4-6의 경우 Count()가 Any()보다 약 2배 더 빨리 수행됩니다.
테이블을 실행할 때.임의(), 다음과 같은 것을 생성합니다(경고: 이해하려고 하는 뇌를 다치게 하지 마십시오).
SELECT
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [Table] AS [Extent1]
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT
1 AS [C1]
FROM [Table] AS [Extent2]
)) THEN cast(0 as bit) END AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
상태에 따라 행을 두 번 스캔해야 합니다.
나는 쓰는 것을 좋아하지 않습니다.Count() > 0
제 의도를 감추고 있기 때문입니다.는 이것에 사용자 합니다.
public static class QueryExtensions
{
public static bool Exists<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
return source.Count(predicate) > 0;
}
}
데이터 세트의 크기와 성능 요구사항에 따라 다릅니다.
거대한 것이 아니라면 가장 가독성이 높은 형태를 사용합니다. 제 자신에게는 어떤 형태든 상관없습니다. 방정식보다는 짧고 읽을 수 있기 때문입니다.
Entity Framework를 사용하고 있고 레코드가 많은 큰 테이블이 있는 경우 Any()가 훨씬 더 빠릅니다.한 번은 테이블이 비어 있고 수백만 개의 줄이 있는지 확인하고 싶었던 적이 있었습니다.Count() > 0을 완료하는 데 20-30초가 걸렸습니다.Any()와 함께 즉시 실행되었습니다.
모든 항목()은 컬렉션을 반복할 필요가 없으므로 성능이 향상될 수 있습니다.그들 중 한 명만 맞으면 됩니다.또는 LINQ-to-Entities의 경우 생성된 SQL은 SELECT COUNT... 또는 SELECT *...가 아니라 IF EXES(...)가 됩니다.
간단한 테스트를 통해 다음 사항을 확인할 수 있습니다.
var query = //make any query here
var timeCount = new Stopwatch();
timeCount.Start();
if (query.Count > 0)
{
}
timeCount.Stop();
var testCount = timeCount.Elapsed;
var timeAny = new Stopwatch();
timeAny.Start();
if (query.Any())
{
}
timeAny.Stop();
var testAny = timeAny.Elapsed;
testCount 및 testAny 값을 확인합니다.
Count() 메서드에 대해서는 IE numberable이 I Collection이면 I Collection의 Count 필드를 검색할 수 있기 때문에 모든 항목에 대해 반복할 수 없습니다. IE numberable이 I Collection이 아닌 경우 MoveNext를 사용하여 잠시 모든 항목에 대해 반복해야 합니다.NET 프레임워크 코드:
public static int Count<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
throw Error.ArgumentNull("source");
ICollection<TSource> collectionoft = source as ICollection<TSource>;
if (collectionoft != null)
return collectionoft.Count;
ICollection collection = source as ICollection;
if (collection != null)
return collection.Count;
int count = 0;
using (IEnumerator<TSource> e = source.GetEnumerator())
{
checked
{
while (e.MoveNext()) count++;
}
}
return count;
}
참조:참조 소스 열거 가능
용사를 합니다.Count()
있는지 작을테기위해하스트업, 나사용그러를 합니다.Any()
의도를 명확하게 하고 코드를 더 쉽게 읽을 수 있도록 합니다.그러나 다음과 같은 경우에 특히 주의해야 합니다.
"EntityFramework"를 호출합니다.Count()
그러면 잠재적으로 대량의 SQL 쿼리가 실행되고 응용 프로그램 데이터베이스에 큰 오버헤드가 발생할 수 있습니다.하기 르기Any()
데이터베이스에도 연결되지만 훨씬 더 효율적인 SQL을 생성합니다.
이 "LINQ 에 포함된 쿼리의 Select()
개체를 생성하는 문, 불필요하게 많은 양의 메모리가 할당될 수 있습니다.하기 르기Any()
그러면 열거형 반복 횟수가 줄어들기 때문에 훨씬 더 효율적입니다.
를 하는 예Any()
:
private static bool IsEmpty(IEnumerable<string> strings)
{
return !strings.Any();
}
저는 100~100만 항목의 요소가 포함된 IList를 사용하여 Count vs Any 중 가장 좋은 항목을 확인할 수 있는 샘플 애플리케이션을 만들었습니다.
코드
class Program
{
static void Main()
{
//Creating List of customers
IList<Customer> customers = new List<Customer>();
for (int i = 0; i <= 100; i++)
{
Customer customer = new Customer
{
CustomerId = i,
CustomerName = string.Format("Customer{0}", i)
};
customers.Add(customer);
}
//Measuring time with count
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
if (customers.Count > 0)
{
Console.WriteLine("Customer list is not empty with count");
}
stopWatch.Stop();
Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);
//Measuring time with any
stopWatch.Restart();
if (customers.Any())
{
Console.WriteLine("Customer list is not empty with any");
}
stopWatch.Stop();
Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);
Console.ReadLine();
}
}
public class Customer
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
결과:
무엇이든 셀 수 없는 것이 좋습니다.
언급URL : https://stackoverflow.com/questions/305092/which-method-performs-better-any-vs-count-0
'source' 카테고리의 다른 글
Xcode 버전을 여러 개 설치할 수 있습니까? (0) | 2023.05.07 |
---|---|
키보드에 브레이크 키가 없을 때 VBA 브레이크 실행을 향상시킵니다. (0) | 2023.05.07 |
ObservableCollection AddRange 메서드를 지원하지 않기 때문에 추가된 각 항목에 대해 알림을 받고, INNotifyCollectionChanging은 어떻게 됩니까? (0) | 2023.05.07 |
WPF 텍스트 블록을 선택할 수 있는 방법이 있습니까? (0) | 2023.05.07 |
Postgresql - 데이터베이스 및 복원을 다른 소유자에게 백업하시겠습니까? (0) | 2023.05.07 |