program story

COUNT (*)해야합니까?

inputbox 2020. 10. 26. 07:58
반응형

COUNT (*)해야합니까?


일반적으로 다음과 같은 쿼리를 수행하는 것이 좋지 않다는 것을 알고 있습니다.

SELECT * FROM `group_relations`

그러나 카운트를 원할 때 테이블이 변경 될 수 있지만 여전히 동일한 결과를 산출하기 때문에이 쿼리를 수행해야합니다.

SELECT COUNT(*) FROM `group_relations`

또는 더 구체적인

SELECT COUNT(`group_id`) FROM `group_relations`

후자가 잠재적으로 더 빠를 수 있다고 생각하지만 다른 고려 사항이 있습니까?

업데이트 :이 경우 InnoDB를 사용하고 있습니다. 구체적이지 않아 죄송합니다.


문제의 열이 NULL이 아니면 두 쿼리 모두 동일합니다. group_id에 null 값이 포함 된 경우

select count(*)

모든 행을 계산하지만

select count(group_id)

group_id가 null이 아닌 행만 계산합니다.

또한 MySQL과 같은 일부 데이터베이스 시스템은 count (*)를 요청할 때 최적화를 사용하여 이러한 쿼리를 특정 쿼리보다 조금 더 빠르게 만듭니다.

개인적으로 계산할 때 null과 함께 안전한 편이되기 위해 count (*)를 수행합니다.


내가 올바르게 기억한다면 MYSQL에서 COUNT (*)는 모든 행을 계산하는 반면 COUNT (column_name)은 주어진 열에 NULL이 아닌 값을 가진 행만 계산합니다.


COUNT (*)는 모든 행을 계산하는 반면 COUNT (column_name)은 지정된 열에서 NULL 값이없는 행만 계산합니다.

MySQL에서 유의해야 할 중요 사항 :

COUNT ()는 행 개수가 캐시되기 때문에 * 또는 null이 아닌 열에 대한 MyISAM 테이블에서 매우 빠릅니다. InnoDB에는 행 개수 캐싱이 없으므로 열이 null 일 수 있는지 여부에 관계없이 COUNT (*) 또는 COUNT (column_name)에 대한 성능 차이가 없습니다. MySQL 성능 블로그 에서이 게시물 의 차이점에 대해 자세히 읽을 수 있습니다 .


SELECT COUNT(1) FROMgroup_relations 를 시도하면 열에서 정보를 검색하지 않기 때문에 조금 더 빠릅니다.

편집 : 방금 조사를 한 결과 이것이 일부 db에서만 발생한다는 것을 알았습니다. sqlserver에서는 1 또는 *를 사용하는 것과 동일하지만 Oracle에서는 1을 사용하는 것이 더 빠릅니다.

http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/9367c580-087a-4fc1-bf88-91a51a4ee018/

분명히 mysql에는 차이가 없습니다. sqlserver처럼 파서가 쿼리를 select (1)로 변경하는 것처럼 보입니다. 어떤 식 으로든 오도하면 미안합니다.


나도 이것에 대해 궁금했다. 문서와 이론적 답변을 읽는 것은 괜찮지 만 경험적 증거와 균형을 이루는 것을 좋아합니다.

5,607,997 개의 레코드가있는 MySQL 테이블 (InnoDB)이 있습니다. 테이블은 내 개인 샌드 박스에 있으므로 내용이 정적이고 아무도 서버를 사용하지 않는다는 것을 알고 있습니다. 나는 이것이 성능에 대한 모든 외부 영향을 효과적으로 제거한다고 생각합니다. 내가 알고있는 auto_increment 기본 키 필드 (Id)가있는 테이블이 있는데 where 절 테스트에 사용할 수있는 null이 아닙니다 (WHERE Id IS NOT NULL).

테스트 실행에서 볼 수있는 유일한 다른 결함은 캐시입니다. 쿼리가 처음 실행될 때 항상 동일한 인덱스를 사용하는 후속 쿼리보다 느립니다. 아래에서이를 캐시 Seeding 호출이라고합니다. 그것을 조금 섞기 위해 나는 어떤 데이터 (TRUE = TRUE)에 관계없이 항상 true로 평가된다는 것을 알고있는 where 절로 실행했습니다.

내 결과는 다음과 같습니다.

QueryType

      |  w/o WHERE          | where id is not null |  where true=true

카운트()

      |  9 min 30.13 sec ++ | 6 min 16.68 sec ++   | 2 min 21.80 sec ++
      |  6 min 13.34 sec    | 1 min 36.02 sec      | 2 min 0.11 sec 
      |  6 min 10.06 se     | 1 min 33.47 sec      | 1 min 50.54 sec

COUNT (ID)

      |  5 min 59.87 sec    | 1 min 34.47 sec      | 2 min 3.96 sec 
      |  5 min 44.95 sec    | 1 min 13.09 sec      | 2 min 6.48 sec

개수 (1)

      | 6 min 49.64 sec    | 2 min 0.80 sec       | 2 min 11.64 sec
      | 6 min 31.64 sec    | 1 min 41.19 sec      | 1 min 43.51 sec

++ 이것은 캐시 Seeding 호출로 간주됩니다. 나머지보다 느릴 것으로 예상됩니다.

결과가 스스로를 대변한다고 말하고 싶습니다. COUNT (Id)는 일반적으로 다른 것보다 낫습니다. Where 절을 추가하면 참으로 평가할 절인 경우에도 액세스 시간이 크게 감소합니다. 스윗 스팟은 COUNT (Id) ... WHERE Id가 NULL이 아닙니다.

다른 사람들의 결과를보고 싶습니다. 아마도 더 작은 테이블이나 계산중인 필드와 다른 필드에 대한 where 절이있을 것입니다. 내가 고려하지 않은 다른 변형이 있다고 확신합니다.


대안 찾기

보시다시피 테이블이 커지면 COUNT쿼리가 느려집니다. 가장 중요한 것은 해결하려는 문제의 본질을 고려하는 것입니다. 예를 들어 많은 개발자 COUNT는 결과 집합의 총 페이지 수를 확인하기 위해 대규모 레코드 집합에 대한 페이지 매김을 생성 할 때 쿼리를 사용 합니다.

COUNT쿼리가 느리게 증가 한다는 것을 알고 있으면 느린 쿼리를 회피 할 수있는 페이지 매김 컨트롤을 표시하는 다른 방법을 고려할 수 있습니다. Google의 페이지 매김이 훌륭한 예입니다.

비정규 화

특정 개수와 일치하는 레코드 수를 반드시 알아야하는 경우 데이터 비정규 화의 고전적인 기술을 고려하십시오. 조회시 행 수를 계산하는 대신 레코드 삽입시 카운터를 늘리고 레코드 삭제시 해당 카운터를 줄이는 것을 고려하십시오.

이를 수행하기로 결정한 경우 멱등 트랜잭션 작업을 사용하여 비정규 화 된 값을 동기화 상태로 유지하는 것이 좋습니다.

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

또는 RDBMS에서 지원하는 경우 데이터베이스 트리거를 사용할 수 있습니다.

Depending on your architecture, it might make sense to use a caching layer like memcached to store, increment and decrement the denormalized value, and simply fall through to the slow COUNT query when the cache key is missing. This can reduce overall write-contention if you have very volatile data, though in cases like this, you'll want to consider solutions to the dog-pile effect.


MySQL ISAM tables should have optimisation for COUNT(*), skipping full table scan.


An asterisk in COUNT has no bearing with asterisk for selecting all fields of table. It's pure rubbish to say that COUNT(*) is slower than COUNT(field)

I intuit that select COUNT(*) is faster than select COUNT(field). If the RDBMS detected that you specify "*" on COUNT instead of field, it doesn't need to evaluate anything to increment count. Whereas if you specify field on COUNT, the RDBMS will always evaluate if your field is null or not to count it.

But if your field is nullable, specify the field in COUNT.


COUNT(*) facts and myths:

MYTH: "InnoDB doesn't handle count(*) queries well":

Most count(*) queries are executed same way by all storage engines if you have a WHERE clause, otherwise you InnoDB will have to perform a full table scan.

FACT: InnoDB doesn't optimize count(*) queries without the where clause


It is best to count by an indexed column such as a primary key.

SELECT COUNT(`group_id`) FROM `group_relations`

It should depend on what you are actually trying to achieve as Sebastian has already said, i.e. make your intentions clear! If you are just counting the rows then go for the COUNT(*), or counting a single column go for the COUNT(column).

It might be worth checking out your DB vendor too. Back when I used to use Informix it had an optimisation for COUNT(*) which had a query plan execution cost of 1 compared to counting single or mutliple columns which would result in a higher figure


if you try SELECT COUNT(1) FROM group_relations it will be a bit faster because it will not try to retrieve information from your columns.

COUNT(1) used to be faster than COUNT(*), but that's not true anymore, since modern DBMS are smart enough to know that you don't wanna know about columns


The advice I got from MySQL about things like this is that, in general, trying to optimize a query based on tricks like this can be a curse in the long run. There are examples over MySQL's history where somebody's high-performance technique that relies on how the optimizer works ends up being the bottleneck in the next release.

Write the query that answers the question you're asking -- if you want a count of all rows, use COUNT(*). If you want a count of non-null columns, use COUNT(col) WHERE col IS NOT NULL. Index appropriately, and leave the optimization to the optimizer. Trying to make your own query-level optimizations can sometimes make the built-in optimizer less effective.

That said, there are things you can do in a query to make it easier for the optimizer to speed it up, but I don't believe COUNT is one of them.

Edit: The statistics in the answer above are interesting, though. I'm not sure whether there is actually something at work in the optimizer in this case. I'm just talking about query-level optimizations in general.


I know it's generally a bad idea to do queries like this:

SELECT * FROM `group_relations`

But when I just want the count, should I go for this query since that allows the table to change but still yields the same results.

SELECT COUNT(*) FROM `group_relations`

As your question implies, the reason SELECT * is ill-advised is that changes to the table could require changes in your code. That doesn't apply to COUNT(*). It's pretty rare to want the specialized behavior that SELECT COUNT('group_id') gives you - typically you want to know the number of records. That's what COUNT(*) is for, so use it.

참고URL : https://stackoverflow.com/questions/457263/should-i-count-or-not

반응형