2016-12-03 2 views
2

순위 시스템 (10 만 명의 사용자가있는 데이터베이스)에 대해 사용자 수를 3 개의 열 합계로 순위를 매기려고합니다. Points_A, Points_BPoints_C. 더 좋은 옵션이 될 것입니다 무엇인지 알고 싶습니다 :열 또는 새 열 합계

  • 순위 페이지를 방문 할 때마다, 합으로 모든 열 및 순서를 합산하여 사용자의 순위를 계산
  • 가 새 열을 만들기 Points_total 세 열의 합계 (다른 열 중 하나가 업데이트 될 때마다 총계를 업데이트 함)와이 Points_total에 의해 쿼리를 정렬합니다.

랭킹 페이지는 매초 여러 번 요청 될 수 있으므로 성능이 매우 중요합니다. 두 번째 옵션이 더 빠르거나 권장되지 않습니까?

+1

최상의 방법은 더 쉬운 방법 (합계를 저장하지 않고)을 시도하고 성능이 * 수용 가능한지 확인하는 것입니다. 어떤 것이 더 낫지 만, 심지어는 더 빠르면 1000 초의 속도가 더 빨라지거나, 120 밀리 초에서 펨토 세컨드 미만의 대기 시간이 걸리더라도, 120 밀리 초는 페이지에 대해 충분히 빠릅니다. 하중. 즉, 성능은 사용자 경험에 극적으로 영향을주는 경우에만 매우 중요합니다. –

답변

3

MySQL 5.7.6에서 생성 된 열을 생성하면 가상 값을 테이블의 다른 열에있는 값을 기반으로 저장할 수 있습니다.

CREATE TABLE tbl (
    Points_A INT, 
    Points_B INT, 
    Points_C INT, 
    Points_total INT AS (Points_A + Points_B + Points_C) 
); 

생성 된 컬럼 정의 문법이있다 : (식) 같이 GENERATED ALWAYS]

COL_NAME의 DATA_TYPE을
    [VIRTUAL | STORED] [UNIQUE [KEY] [COMMENT 코멘트]
    [[NOT] NULL] [[PRIMARY] KEY]

당신은 (당신이 필요에 따라 다름) VIRTUAL 또는 STORED 사용하도록 결정할 수 있습니다.

MySQL 5.7.8에서 마찬가지로 INDEXes on virtual columns을 추가 할 수 있습니다. 따라서 귀하의 경우에는 정확히 찾고있는 것입니다 (이 방법으로 열의 값이 색인됩니다).

5.7.8보다 오래된 MySQL을 사용하고 있고 순위 페이지가 여러 번 액세스되는 경우 - 특정 열의 계산 된 값과 동일한 값을 지정하고 해당 열에 인덱스를 추가하는 것이 좋습니다.

+0

OP에 수만 명의 사용자가있는 경우 요구 사항에 대한 색인이 필요할 수 있습니다. –

+0

주의 : 어떤 시점에서 (수백만 명의 사용자가?) 반복적으로 색인을 업데이트하는 비용은 금지됩니다. 비용은 본질적으로 "BTree (인덱스)에서 행을 삭제하고 다른 곳에서 다시 삽입"합니다. –

0

생각해보십시오. 순위가 매번 변경 될 때마다 비용이 많이 드는 작업을 수행하는 대신 복잡한 접근 방법이 더 좋은지 알아보십시오.

하지만 먼저이 값은 Points에만 달려 있습니다. 또한 상위 10 위 만 필요하다고 가정합니다. "나는 10000에서 7654로 등급이 매겨졌다"는 것을 발견하지 않아도된다)

등급이 올라갈 때마다 반응하는 방아쇠 (또는 앱 코드)를 설정한다. 포인트를 함께 더하고 임계 값을 확인합니다. 10 위 아래라면 아무 것도하지 마십시오.

이상인 경우 SELECT ... ORDER BY ... LIMIT 10을 수행하여 새로운 "상위 10 개"를 얻고 결과를 별도의 테이블에 저장하십시오. 또한 임계 값을 갱신하십시오.

혜택 :

  • 이 별도의 표는 '여러 번 각 초'액세스하지만, 기본 테이블이 할 필요는있는 것이다.
  • 시간이 가장 적게 걸리는 시간은? (그러나 많은 수의 upvoted 것들에 대한 더 많은 일을하고있다.)
  • 메인 테이블 (10K 행)에서 순위 표시 테이블 (10 행)을 분리함으로써 잠금 경합을 줄입니다.
  • 쿼리 캐시 사용 사례가 될 수 있습니다
    • 전원을 켜고 그것을,
    • 가 (너무 큰되지 않음) query_cache_size = 20M을 설정
    • query_cache_type = DEMAND
    • 이 순위 SELECTSQL_CACHE를 추가; 다른 대부분의 SELECTsSQL_NO_CACHE을 추가하십시오. 은 "톱 50"를 절약 고려하면 "10"의 한 페이지 이상이 필요한 경우

. 처음 5 페이지에는 새 테이블로 충분합니다. 6 페이지 이상에서는 어려운 방법입니다 (10K 행 테이블을 스캔하십시오). 바라기를, 이것은 아직도 이점이 있기 위하여 희소 할 것이다.