private-message-topic-tracking-state.json 로딩이 느립니다

아, 그렇군요. 이 쿼리는 잘 처리되지 못할 것 같습니다. 최신 버전으로 업데이트하신 후, mini_profiler에서 해당 쿼리를 추출해서 explain analyze를 실행해 주시고 결과를 공유해 주시겠어요?

Meta(RDS db.r6g.large 30GB)에서는 다음과 같은 결과가 나옵니다:

1개의 좋아요

다시 explain analyze를 실행해 보겠지만, 해당 쿼리를 성공적으로 완료하지는 못했습니다.

업데이트: 이 커밋은 아무것도 변경하지 않았습니다. 업데이트 후에도 데이터베이스는 여전히 지속적으로 95% 이상으로 과부하 상태이며, 기존에 실행 중이던 모든 쿼리를 종료시키고 있습니다. 베타4 버전에서는 이 포럼의 경우 안정적으로 20~30% 수준에서 실행되었습니다. 이미 자동 진공(auto-vacuum)과 스키마 재인덱싱도 실행했습니다.

이 기능을 비활성화하는 방법은 무엇인가요? 이를 해결하기 위해 더 큰 데이터베이스 인스턴스를 사용하는 것은 적절해 보이지 않으며, 이 업데이트 이전에는 해당 쿼리가 정상적으로 잘 작동했다는 점을 고려하면 쿼리 계산 방식에 문제가 있는 것으로 보입니다.

쿼리가 약 21분 후에 마침내 완료되었습니다

또한, 출력 결과가 꽤 많이 달라지는 것 같아서 PG 10.17을 사용 중이라는 점도 참고해 주시면 좋겠습니다.

1개의 좋아요

우리는 */private-messages-all/* 라우트를 일시적으로 */private-messages/*로 재라우팅하는 방식으로 문제를 monkey-patch(원본 코드 수정 없이 동적으로 메서드/함수를 교체하는 기법)로 해결했습니다. 그 결과 "모든 받은 편지함(all inboxes)"은 "개인(Personal)"과 동일한 콘텐츠를 표시하지만, 적어도 이 방식으로 인해 CPU 사용률이 지속적으로 100%에 달하는 문제를 겪을 필요가 없습니다.

Monkey-patch 코드:

# name: discourse-private-messages-perf-hotfix
# version: 0.0.1
# authors: 

# 기존 라우트를 오버라이드하기 위해 prepend 사용
Discourse::Application.routes.prepend do
  scope path: nil, constraints: { format: /(json|html|\*\/\*)/ } do
    scope "/topics", username: RouteFormat.username do
      # 모든 */private-messages-all/* 라우트를 대신 */private-messages/*(개인 메시지)로 재라우팅
      # 전자는 비용이 많이 들고, 후자는 저렴하여 상당한 데이터베이스 CPU 사용량을 절약할 수 있음
      get "private-messages-all/:username" => "list#private_messages", as: "topics_private_messages_override", defaults: { format: :json }
      get "private-messages-all-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent_override", defaults: { format: :json }
      get "private-messages-all-new/:username" => "list#private_messages_new", as: "topics_private_messages_new_override", defaults: { format: :json }
      get "private-messages-all-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread_override", defaults: { format: :json }
      get "private-messages-all-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive_override", defaults: { format: :json }
    end
  end
end

위 monkey-patch 배포 후 우리 포럼 데이터베이스의 CPU 사용률:

@tgxworld */private-messages-all/* 라우트가 무엇을 하고 있는지 다시 한번 확인해 주실 필요가 있습니다. 구현 방식에 명확한 문제가 있으며, 대규모 포럼 데이터베이스에는 효율성이 부족합니다. 구현이 올바른 데이터베이스 인덱스를 사용하지 않고 있거나, 쿼리 생성 과정에서 매우 비용이 높은 쿼리가 생성되고 있는 것입니다(특히 PSQL 10에서 그러하며, 12/13에서는 확실하지 않음).

현재 구현 방식은 사실상 우리 포럼을 마비시켜 CPU 사용률을 약 15%에서 지속적으로 100%로 올리고, 포럼의 다른 모든 기능에서 성능 저하를 유발했습니다. 개인/그룹 받은 편지함 쿼리는 50ms 미만으로 처리되는데, “모든 받은 편지함” 쿼리는 완료하는 데 20분 이상 걸리는 이유를 알 수 없습니다.

직전 게시된 @forkythetoy의 analyze 덤프를 사용하여 20분 이상 걸리던 실행 전 상태를 확인해 볼 수 있습니다.

1개의 좋아요

@Falco 방금 여기서 우리의 주제를 병합하신 걸 확인했습니다. 하지만 실제로는 다른 엔드포인트에 관한 내용인 것 같습니다. 이 버그 리포트는 private-message-topic-tracking-state 엔드포인트에 관한 것이지만, 우리가 이야기하고 있는 것은 */private-messages-all/*입니다. 이로 인해 일부 혼동이 발생했을 수 있으니 죄송합니다. (처음에 이 주제를 링크했을 때 그 혼동의 시작이 되었을 수도 있습니다)

우리 포럼에서는 private-message-topic-tracking-state가 빠르므로, 이 문제는 우리에게 해당되지 않습니다.

우리 쪽에서는 이 쿼리가 데이터베이스 처리에 약 200~300ms가 소요됩니다. 예상보다 약간 길지만, 여전히 정상 범위 내에 있다고 볼 수 있습니다.

현재 Postgres 13을 사용 중입니다.

1개의 좋아요

@Hooksmith 수정안이 준비 중입니다

5개의 좋아요

@Hooksmith @forkythetoy PG 13으로 업데이트할 수 있을까요? 현재 Discourse가 요구하는 최소 버전입니다. 또한 쿼리가 동일한 PG 버전으로 실행되지 않으면 쿼리 플랜을 비교하기가 더 어렵습니다.

새로운 쿼리의 성능이 사용자별로 차이가 너무 커서 이 변경 사항을 되돌려야 했습니다.

1개의 좋아요

@blattersturm 여전히 토픽 추적 상태의 성능이 느린 것을 확인하고 계신가요?

확실하지 않습니다. 며칠 동안 업그레이드를 하지 않았거든요. 개선 여부를 확인해 보기 위해 적용할 커밋이 있을까요?

아니요, 아무것도 변경되지 않았습니다. 하지만 쿼리에 대한 EXPLAIN ANALYZE 결과를 제공해 주시면 도움이 될 것입니다.

1개의 좋아요

성능상의 우려로 인해 현재 모든 수신함을 되돌려 놓았습니다.

3개의 좋아요

이 주제는 14일 후 자동으로 닫혔습니다. 더 이상 답변을 게시할 수 없습니다.