수백만 개의 레코드가있는 테이블에 대한 실시간 집계

서투른 솜씨

현재 약 5 백만 개의 레코드를 포함하는 계속 늘어나는 테이블을 다루고 있습니다. 매일 약 100,000 개의 새 레코드가 추가됩니다.

이 테이블에는 광고 캠페인에 대한 정보가 포함되어 있으며 쿼리를 통해 다른 테이블과 결합됩니다.

CREATE TABLE `statistics` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `ip_range_id` int(11) DEFAULT NULL,
    `campaign_id` int(11) DEFAULT NULL,
    `payout` decimal(5,2) DEFAULT NULL,
    `is_converted` tinyint(1) unsigned NOT NULL DEFAULT '0',
    `converted` datetime DEFAULT NULL,
    `created` datetime DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `created` (`created`),
    KEY `converted` (`converted`),
    KEY `campaign_id` (`campaign_id`),
    KEY `ip_range_id` (`ip_range_id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

다른 테이블에는 IP 범위가 포함되어 있습니다.

CREATE TABLE `ip_ranges` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `ip_range` varchar(11) NOT NULL,
    PRIMARY KEY (`id`),
    KEY `ip_range` (`ip_range`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

집계 쿼리는 다음과 같습니다.

SELECT
    SUM(`payout`) AS `revenue`, 
    (SELECT COUNT(*) FROM `statistics` WHERE `ip_range_id` = `IpRange`.`id`) AS `clicks`, 
    (SELECT COUNT(*) FROM `statistics` WHERE `ip_range_id` = `IpRange`.`id` AND `is_converted` = 1) AS `conversions` 
FROM `ip_ranges` AS `IpRange` 
INNER JOIN `statistics` AS `Statistic` ON `IpRange`.`id` = `Statistic`.`ip_range_id`
GROUP BY `IpRange`.`id` 
ORDER BY `clicks` DESC 
LIMIT 20

쿼리를 완료하는 데 약 20 초가 걸립니다.

이것은 EXPLAIN이 반환하는 것입니다.

id  select_type         table       type   possible_keys    key          key_len  ref               rows    Extra

1   PRIMARY             ip_range    index  PRIMARY          PRIMARY      4        NULL              306552  Using index; Using temporary; Using filesort
1   PRIMARY             statistic   ref    ip_range_id      ip_range_id  5        db.ip_range.id    8       Using where
3   DEPENDENT SUBQUERY  statistics  ref    ip_range_id      ip_range_id  5        func              8       Using where
2   DEPENDENT SUBQUERY  statistics  ref    ip_range_id      ip_range_id  5        func              8       Using where; Using index

ip_ranges 테이블의 클릭 및 전환을 추가 열로 캐싱하는 것은 옵션이 아닙니다. campaign_id 열 (및 향후 다른 열)도 필터링 할 수 있어야하기 때문입니다. 따라서 이러한 집계는 다소 실시간이어야합니다.

여러 차원에서 거의 실시간으로 큰 테이블에서 집계를 수행하는 가장 좋은 전략은 무엇입니까?

필자는 단순히 쿼리를 더 좋게 만들려는 것은 아니지만 다른 데이터베이스 시스템 (NoSQL)을 포함하거나 다른 서버에 데이터를 배포하는 등의 전략에도 관심이 있습니다.

Thorsten Kettner

쿼리가 지나치게 복잡해 보입니다. 동일한 테이블을 반복해서 쿼리 할 필요가 없습니다.

select
  sum(payout) as revenue, 
  count(*) as clicks, 
  sum(s.is_converted = 1) as conversions 
from ip_ranges r
inner join statistics s on r.id = s.ip_range_id
group by r.id 
order by clicks desc 
limit 20;

수정 (승인 후) : 다음과 같은 작업을 처리하는 방법에 대한 실제 질문에 관해서는 :

테이블의 모든 데이터 를보고 결과를 최신 상태로 유지하려고합니다 . 그러면 모든 데이터를 읽는 것 외에 다른 옵션이 없습니다 (전체 테이블 스캔). 테이블이 넓다면 (즉, 많은 열이있는 경우) 커버링 인덱스 (예 : 관련된 모든 열을 포함하는 인덱스)를 생성 할 수 있으므로 테이블을 읽는 대신 인덱스를 읽습니다. 글쎄, 또 뭐야? 전체 테이블 스캔에서는 내가 아는 한 MySQL이 제공하지 않는 병렬 액세스를 사용하는 것이 좋습니다. 따라서 다른 DBMS로 전환 할 수 있습니다. 그런 다음 DBMS가 제공하는 다른 기능을 확인하십시오. 병렬 쿼리는 테이블을 분할하면 도움이 될 수 있습니다. 마지막으로 떠오르는 것은 하드웨어, 즉 더 많은 CPU, 더 빠른 드라이브 등입니다.

또 다른 옵션은 테이블에서 오래된 데이터를 제거하는 것입니다. 올해의 세부 정보가 필요하지만 이전 연도의 집계 데이터 만 필요하다고 가정 해보십시오. 그런 다음 필요한 합계와 개수 만 포함하는 다른 테이블 old_statistics를 만듭니다.

table old_statistics
(
  ip_range_id,
  revenue,
  conversions
);

그런 다음 통계에서 데이터를 집계합니다.이 데이터는 현재 연도의 데이터 만 보유 할 것이기 때문에 훨씬 더 작을 것이고, 결과를 얻기 위해 old_statistics를 추가합니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

간단한 테이블에 대한 MySql 합계 및 개수

분류에서Dev

해시 테이블에 대한 의심되는 SBCL 가비지 수집 버그

분류에서Dev

KDB : 테이블에 대한 사용자 정의 집계 함수

분류에서Dev

SQL Server, 테이블의 여러 열에 대한 집계 (수)

분류에서Dev

HBase 테이블의 column family에있는 레코드 수 계산

분류에서Dev

매개 변수에 대한 관계의 z3 인코딩 테이블

분류에서Dev

하나의 컨트롤러에서 두 개의 다른 테이블에 대한 레코드를 만드는 것이 나쁜 습관으로 간주됩니까?

분류에서Dev

집계 된 개수가있는 레코드의 평균 찾기

분류에서Dev

열 3에 최대 개수가있는 한 테이블에서 2 개의 열을 표시하고 다른 테이블에서 계산 된 값의 합계를 표시합니다.

분류에서Dev

2 개의 테이블에서 레코드 수 가져 오기-일대 다 관계

분류에서Dev

10 만 개의 레코드 테이블 쿼리 중 실행 시간 초과

분류에서Dev

Oracle 새 인덱스가있는 새 테이블에 대한 테이블 통계를 수집해야합니까?

분류에서Dev

3 개의 테이블에 대한 SQL 집계

분류에서Dev

3 개의 다른 테이블 기반 데이터 쿼리-테이블에 일치하는 레코드가 있는지 확인한 다음 표시

분류에서Dev

Spark에서 백분위 수를 계산하기 위해 Groupby 집계의 실행 시간을 개선하는 방법은 무엇입니까?

분류에서Dev

데이터 프레임의 집계 값에 대한 요약 테이블

분류에서Dev

Postgresql에서 한 열에 M 개의 고유 값이있는 테이블에서 알 수없는 레코드 수를 어떻게 가져올 수 있습니까?

분류에서Dev

1 대 N 관계가있는 테이블을 N 레코드의 마지막 값이있는 레코드 한 줄로 결합

분류에서Dev

500 개 미만의 레코드가있는 테이블 만 스캔하도록 SQL 쿼리 제한

분류에서Dev

수백만 개의 시계열 데이터를 Cassandra DB에 효율적으로 삽입하는 방법에 대한 조언이 필요합니다.

분류에서Dev

사용자가 Rails에서 레코드를 편집 할 수있는 시간을 어떻게 제한합니까?

분류에서Dev

변수 입력에 대한 Matlab 코드의 실행 시간을 어떻게 계산합니까?

분류에서Dev

쿼리의 각 레코드에 대한 테이블 함수

분류에서Dev

데이터베이스에 대한 MySQL 작업에는 수백만 개의 행이있는 테이블이 포함됩니다.

분류에서Dev

테이블에 대한 mysqldump는 하나의 레코드 만 덤프합니다.

분류에서Dev

Oracle-수백만 개의 행이있는 테이블에 적합한 일일 파티셔닝 접근 방식

분류에서Dev

고정 된 수의 열이있는 테이블에 레코드 표시

분류에서Dev

한 데이터베이스 트립에서 여러 테이블의 집계 함수에 해당하는 Linq

분류에서Dev

SHARE 잠금 레코드의 동작, 집계 함수가 불가능한 이유는 무엇입니까?

Related 관련 기사

  1. 1

    간단한 테이블에 대한 MySql 합계 및 개수

  2. 2

    해시 테이블에 대한 의심되는 SBCL 가비지 수집 버그

  3. 3

    KDB : 테이블에 대한 사용자 정의 집계 함수

  4. 4

    SQL Server, 테이블의 여러 열에 대한 집계 (수)

  5. 5

    HBase 테이블의 column family에있는 레코드 수 계산

  6. 6

    매개 변수에 대한 관계의 z3 인코딩 테이블

  7. 7

    하나의 컨트롤러에서 두 개의 다른 테이블에 대한 레코드를 만드는 것이 나쁜 습관으로 간주됩니까?

  8. 8

    집계 된 개수가있는 레코드의 평균 찾기

  9. 9

    열 3에 최대 개수가있는 한 테이블에서 2 개의 열을 표시하고 다른 테이블에서 계산 된 값의 합계를 표시합니다.

  10. 10

    2 개의 테이블에서 레코드 수 가져 오기-일대 다 관계

  11. 11

    10 만 개의 레코드 테이블 쿼리 중 실행 시간 초과

  12. 12

    Oracle 새 인덱스가있는 새 테이블에 대한 테이블 통계를 수집해야합니까?

  13. 13

    3 개의 테이블에 대한 SQL 집계

  14. 14

    3 개의 다른 테이블 기반 데이터 쿼리-테이블에 일치하는 레코드가 있는지 확인한 다음 표시

  15. 15

    Spark에서 백분위 수를 계산하기 위해 Groupby 집계의 실행 시간을 개선하는 방법은 무엇입니까?

  16. 16

    데이터 프레임의 집계 값에 대한 요약 테이블

  17. 17

    Postgresql에서 한 열에 M 개의 고유 값이있는 테이블에서 알 수없는 레코드 수를 어떻게 가져올 수 있습니까?

  18. 18

    1 대 N 관계가있는 테이블을 N 레코드의 마지막 값이있는 레코드 한 줄로 결합

  19. 19

    500 개 미만의 레코드가있는 테이블 만 스캔하도록 SQL 쿼리 제한

  20. 20

    수백만 개의 시계열 데이터를 Cassandra DB에 효율적으로 삽입하는 방법에 대한 조언이 필요합니다.

  21. 21

    사용자가 Rails에서 레코드를 편집 할 수있는 시간을 어떻게 제한합니까?

  22. 22

    변수 입력에 대한 Matlab 코드의 실행 시간을 어떻게 계산합니까?

  23. 23

    쿼리의 각 레코드에 대한 테이블 함수

  24. 24

    데이터베이스에 대한 MySQL 작업에는 수백만 개의 행이있는 테이블이 포함됩니다.

  25. 25

    테이블에 대한 mysqldump는 하나의 레코드 만 덤프합니다.

  26. 26

    Oracle-수백만 개의 행이있는 테이블에 적합한 일일 파티셔닝 접근 방식

  27. 27

    고정 된 수의 열이있는 테이블에 레코드 표시

  28. 28

    한 데이터베이스 트립에서 여러 테이블의 집계 함수에 해당하는 Linq

  29. 29

    SHARE 잠금 레코드의 동작, 집계 함수가 불가능한 이유는 무엇입니까?

뜨겁다태그

보관