Extra Form
PHP PHP 7.4
CMS Rhymix 2.0

쿼리 날릴 때 rand()로 정렬을 하면 데이터 량이 조금만 많아져도 큰 부담이 되는 것으로 알고 있습니다.

 

지금은 회원들 중에서 친구가 아닌 회원들을 랜덤으로 뽑아서 추천해주는 기능을 만들고 있는데요.

그러다보니 ORDER BY rand()에서 딱 걸리더라구요.

 

그러다 스택오버플로우에서

https://stackoverflow.com/questions/1823306/mysql-alternatives-to-order-by-rand#answer-36013954

https://stackoverflow.com/questions/1823306/mysql-alternatives-to-order-by-rand#answer-40780130

이 두 가지 답변을 봤습니다.

 

이해한 바로는 테이블에서 미리 랜덤으로 (원하는 갯수만큼?) 데이터를 뽑아와서 테이블에 조인시켜서 범위를 축소시키는 것 같은데 이거는 부하가 덜 걸리는 건가요?

암튼 이런 접근이 실제로 효과가 있는 건가요? 그리고 어떤 점에서 유리하다는 건가요?

궁금합니다!

  • profile

    최종 갯수를 지정하여 가져와서 처리한다면 이렇게 하면 되겠네요..

    보통 rand()자체가 오래걸리는 문제는 당연히 처음부터 모든 회원을 전부 통째로 가져오는 문제점때문일겁니다.

    그래서 저기에서 말하는건 member_srl을 전체 갯수중에 일부 시작점 + 끝점 해서 일부를 가져온다음 그부분에서 rand를 돌린다 이런 개념으로 보면되는데요..

    예를들어 현재 최대 시퀀스값을 가져온다음 1부터 최대시퀀스 까지 랜덤을 돌려서 나온 숫자를 가지고 가려내면 되겠지요.

    그래서 만약 50이 떴다면 50 + 100 해서 50~150까지 포함되어있는 member_srl 값을 가져온다 이런식으로요..

    이렇게 하면 최대 많아야 100명이고 갯수를 줄일 수 있겟지요.(최대 랜덤은 100을 넘기지 않는게 좋긴해서..)

    근데 회원가입현황이 많이 없는 상황이라면 시퀀스가 100개 넘어가도록 회원가입한 적이 없다면 0명일 가능성이 있습니다. 이렇게 하면 무한적으로 계속 반복될 수 있어서...

    사이트 마다 그 랜덤에 사용될 갯수를 적절하게 설정하여 사용할 수 있도록 제공해주는 편이 나을수 있겠습니다.


    랜덤으로 뭔가 뽑아온다는 거 자체가 좀 애매하긴해요 ㅎㅎ

    특히 RX와 같은 경우라면 getNextSequece함수로 고유번호를 다 등록해놓는 구조이다보니 아에 index를 지정하여 넣는 방식보단 제작도 까다롭구요 ㅋㅋㅋ

     

    아 아니면.. 최소값에서 최대 srl값을 가져왔을때 진짜 마지막 높은 숫자 나오기전까지는 모르겟지만 listcount 를 20개로 돌려서 그걸 새로운 array쪽에 새롭게 데이터를 몰아넣은다음 index 값을 rand으로 한번더 추첨 해주는 방식으로 들어가면 좀더 깔끔하겠어요. (이때 offset 쿼리방식으로 page변수를 쿼리로 넣지 않도록 주의해주세요.)

  • profile profile

    min이랑 max 뽑아오고, rand()로 숫자 하나를 기준값으로 추출한 다음, 그보다 큰 member_srl의 회원 데이터를 뽑아보라는 말씀이신 거죠?
    기준값이 max에 가깝게 추첨되면 리스트가 부족해질 것도 같은데, 소수정예로(?) 추천을 한다면 생각해볼 만한 방법인 것 같습니다.

  • profile
    친구를 랜덤으로 뽑아오는 것은 괜찮습니다. 전체 회원 중 친구의 비율은 얼마 안 될 테니까요.

    친구가 아닌 회원을 랜덤으로 뽑아오면 곤란합니다. 사실상 전체 회원을 모두 랜덤으로 정렬한 후 상위 n명만 뽑아오는 형태가 됩니다.

    1200ms짜리 쿼리를 300ms로 줄였다고 좋아하는 사람이 보이는데, 그런 꼼수는 무시하시기 바랍니다. 커뮤니티 사이트는 300ms가 아니라 30ms의 쿼리 시간도 감당할 수 있는 환경이 아닙니다. 회원이 10만 명이라도 1ms 이내에 쿼리할 수 있어야 하고, 그렇지 않다면 애당초 그런 시한폭탄 같은 기능은 만들지 않으셔야 나중에 스트레스받지 않아요.

    성능 문제 걱정없이 랜덤 정렬을 구현하는 거의 유일한 방법은 백그라운드(crontab)에서 미리 셔플링해서 정렬 순서를 고정시켜 두는 것입니다. 대략 1시간마다 다시 셔플링한다면 사용자 입장에서는 충분히 랜덤하게 보이겠지요.
  • profile profile
    안 그래도 300ms라 그래서 '뭐지? 라이믹스 사용자 앞에서 자랑할 속도인가?' 싶긴 했어요.
    크론탭이라니... 웹호스팅에선 안 되겠네요ㅜ
  • profile profile
    웹크론이라는 것이 있으니, 필요한 사람은 쓰라고 하면 됩니다.^^
  • ?
    이렇게 해보시는건 어떠신지요?
    php에서 랜덤 함수를 원하는 만큼 돌리고 배열에 담아두고, 범위는 회원수만큼
    이미 친구라면 그 번호는 다시뽑거나, 단순히 번호를 ± 해버려도 될것이고요

    WHERE member_srl IN (배열에 담아둔 값)

    예시
    WHERE member_srl IN (10,102,32,4)
  • ? profile
    좋은 방법인 것 같은데요. 다만 member_srl이 연속되는 일련번호가 아니라 듬성듬성 분포해 있어서 결과적으론 member 테이블에서 랜덤하게 데이터를 뽑아오는 방식과 그다지 차이가 있을지는..
  • profile
    친구 추천을 정말 랜덤으로 해버린다면 비활성 회원이 뽑혀나올 가능성도 있습니다. 이미 친구 추가한 회원이 나올 가능성도 배제할수 없고요.

    예를 들어 마스토돈의 경우 redis 캐시에 해당 사용자와 교류한 사용자에게 점수를 부여(답글은 1점, 좋아요는 10점, 리블로그(트위터 리트윗 비슷한 기능)은 20점)한 뒤 이 점수를 기반으로 팔로우할 사용자를 추천해줍니다.

    비슷하게 해당 사용자가 댓글을 작성한 글 작성자, 대댓글을 작성한 댓글 작성자와 같이 교류가 이루어진 적이 있는 사용자에게 점수를 부여한 뒤 이 점수에 따라 친구 추천 목록을 구성한다면 단순 랜덤 픽보다 친구추가가 실제 이루어질 가능성이 더 높을것 같습니다.

    물론 초기 데이터는 (일정주기로 바뀌는) 랜덤 데이터가 적합하겠습니다.
  • profile profile
    오오 이거 되게 좋은 접근인 것 같습니다.
    지금은 스킨 작업이지만 나중에 따로 모듈화해보면 좋을 것 같아요.
    (이래서 댓글도 스크랩을 해야 하는데...)
  • profile
    다행히 회원 수 24만명에 적용해봤는데 지연없이 잘뜨네요.
    몇 백만명은 되어야지 아마 지연이 있나보네요.
    YJSoft님 말씀데로 비활성회원이네요.

    너무 신기해서 자꾸 새로고침중입니다 ㅎㅎ
  • profile profile
    24만명 ㄷㄷㄷㄷ
    최근 활동이력 기준으로 선별을 해서 랜덤 추출도 해봐야겠네요