programing

mysql에서 읽지 않은 기사를 가져오기 위한 데이터베이스 설계(1억 개 이상의 행 테이블)

projobs 2022. 9. 15. 23:02
반응형

mysql에서 읽지 않은 기사를 가져오기 위한 데이터베이스 설계(1억 개 이상의 행 테이블)

이 정보는 매우 요약되어 있다.

테이블이 두 개 있어요.

기사

-----------------------------------
|id | weight | text               |
-----------------------------------
|1  | 10     | blah               |
|2  | 100    | blah               |
|3  | 50     | blah               |
|4  | 1000   | blah               |
-----------------------------------

읽어주세요

-----------------------------------
| user_id | article_id            |
-----------------------------------
| 1       | 4                     |
| 1       | 2                     |
| 1       | 3                     |
| 2       | 3                     |
| 2       | 4                     |
-----------------------------------

아래 쿼리를 사용하여 읽지 않은 기사를 가져오고 싶다(매우 요약됨)

SELECT 
    a.* 
FROM 
    article a LEFT OUTER JOIN read r ON r.article_id = a.id and r.user_id = 1
WHERE 
    r.id IS NULL
ORDER BY
    a.weight DESC
LIMIT 10

중요한 정보

  1. 개수read table행은 사용자당 1000 미만입니다.(오래된 데이터 삭제)
  2. 기사 테이블의 가중치 열이 자주 변경됩니다. (순서가 고정되지 않은 것을 의미합니다.)

문제는..(사용자 수: 100만 이상일 때)

  1. 읽기 표를 사용하여 읽지 않은 문서를 가져오는 방법(내부 조인은 중요하지 않습니다)
    • 의 수read table행은 1G를 넘습니다.

지금까지는 잘 되고 있지만(현재 읽기 테이블 행 수 : 100M), 사용자가 급증하고 있어 다음 단계를 준비해야 합니다.

이 경우 대규모 서비스를 위한 최선의 방법은 무엇입니까?

(샤딩? 칸막이 테이블?)아키텍처를 재설계할 수 있습니까?)

잘 부탁드립니다

  • 컬럼 추가article기사를 읽었는지 읽지 않았는지 여부를 나타내는 플래그가 됩니다.(사용자 수나 타임스탬프로 하지 마십시오.그렇게 하면 이후의 스텝이 느려집니다.)
  • 사용자가 기사를 읽을 때마다 플래그를 확인하고 필요에 따라 변경합니다.
  • INDEX(flag, weight, id)가 있습니다.이것에 의해, 쿼리가 거의 즉시 실행됩니다.저 백만 줄 테이블 위에서는 이 정도면 될 거야.

문제:(1000 이후) 삭제 중이기 때문에 일부 "읽기" 기사는 "읽지 않음"이 될 수 있습니다.이 문제를 해결하려면 삭제를 배치하고 제거된 개별 문서 목록을 수집하십시오.그런 다음 플래그를 재계산하는 지루한 작업을 수행합니다. 단, 기사만 해당됩니다. INDEX(article_id)도움이 되다; 사용하다EXISTS ( SELECT * FROM read WHERE article_id = $aid )(이는 한 번에 한 가지 보조가 아닌 배치 조작으로 전환될 수 있습니다.)

또 다른 문제: 10억 행 테이블의 보조 키는 비용이 많이 듭니다. 많은 I/O가 발생할 수 있습니다.이 문제에 대처하기 전에 다음을 제공하십시오.SHOW CREATE TABLE두 테이블 모두에 대해, 그리고 다른 공통에 대해SELECTs. 적절한 인덱스와 데이터형을 선택하는 것은 10억 행 테이블에서의 퍼포먼스에 매우 중요합니다.

포인트는 가능한 한 인덱스를 사용하는 것입니다.

SELECT a.* 
FROM  a
LEFT JOIN read r 
  ON r.article_id = a.id and r.user_id =1 
WHERE r.id IS NULL 
ORDER BY a.weight DESC
LIMIT 10

편집: 관심사는 데이터 크기입니다.read데이터 크기를 줄여야 합니다.그러기 위해서는 여러 가지 옵션이 있습니다.

  • MySQL 파티션: user_id 범위에 파티션을 만듭니다(파티션당 사용자 수는 10만 명일 수 있습니다.
  • 여러 테이블 만들기:분할과 비슷하지만, 데이터는 다른 데이터베이스(다른 DB 서버에도 있음)에 있습니다.user_id에 따라 가입할 테이블/데이터베이스를 결정합니다.

또한 오래된 데이터를 정기적으로 아카이브하는 것을 고려할 수 있습니다.어플리케이션은 아카이브된 테이블을 조회해야 하는지 라이브 테이블을 조회해야 하는지 결정할 수 있을 정도로 스마트해야 합니다.

언급URL : https://stackoverflow.com/questions/31553462/database-design-for-getting-unread-article-in-mysql-over-100m-row-table

반응형