본문 바로가기
Mysql

스테이지 스코어 저장.

by NaHyungMin 2019. 3. 11.

유저 게임 STAGE별 점수 데이터가 필요하는 요청.

STAGE는 현재 300개가 존재한다. 


문제1. 유저 한명당 300개의 Column을 집어 넣을 것인가.

문제2. 게임을 자주 하지 않거나 아예 안하는 유저들이 존재.

문제3. 테이블이 커지면 인덱스도 커진다. 속도 저하.

문제4. Insert를 자주 일어나게 할것인가. 처음에 Insert 후 Update를 사용할 것 인가.


생각1. 그러면 유저 한 명당 6개의 레코드와 50개의 필드로 나눌 것인가. 아니면 더 증가 가능. 10 x 30

생각2. 100만 레코드로 조금씩 조회가 느려진다면. 10만명이 게임을 하면 100만 레코드.

생각3. 테이블을 미리 나눈다면. 어떻게 관리할 것인가.


결론1. STAGE 클리어를 전부 하지 않으니 해당 스테이지를 업데이트할 때 넣자. 근데 구분은 어떻게 하냐... 1~10?

결론2. 레코드는 유저당 10개 X 32개의 필드(user_key, StageRange, Stages..)

결론3. 기본키는 user_key + StageRange

결론4. 평균 클리어 200이라고 가정 하에. Range 7 X User Count 200,000 = 140만 레코드.


StageRange 산출법 = 30 = 1, 60 = 2, 90 = 3..


테이블 명 홀/짝. odd number, Even Numbers(user_stage_score_odd, user_stage_score_even)


 #stage_range

 set $stage_range = truncate((($stage - 1) / 30) + 1, 0); #convert((($stage - 1) / 30) + 1, SIGNED); 반올림 처리됨

 

 #스테이지 30마다. column 계산.

 select $stage - (30 * ($stage_range - 1));

 select 1 - (30 * (1 -1));



테이블 정보. user_stage_score_odd와 user_stage_score_even 두 가지로 나눈다. 홀/짝수별 유저 정보.



CREATE DEFINER=`nahyungmin`@`%` PROCEDURE `sub_sp_UserStageScore`(
in $user_key bigint
, in $stage int
, in $clear_score int)
proc_label:BEGIN
declare $stage_range int; #range
declare $temp int;
declare $update_coulmn char(7);
declare $update_table varchar(25);
set $stage_range = truncate((($stage - 1) / 30) + 1, 0);
#select, insert fn. 유저 검색 후 데이터 없으면 insert.
set $temp = fn_UserStageRecord($user_key, $stage);
#update table.
if(($user_key % 2) = 1) then #odd
set $update_table = "user_stage_score_odd";
else #even
set $update_table = "user_stage_score_even";
end if;
#update column.
set $update_coulmn = concat("stage", $stage - (30 * ($stage_range - 1)));
set @clear_score = $clear_score;
set @user_key = $user_key;
set @stage_range = $stage_range;
set @clear_score2 = $clear_score;
#select concat("update ", $update_table, " set ", $update_coulmn, "=?", " where user_key = ? and stage_range = ? and ", $update_coulmn, " < ?");
set @query_string = concat("update ", $update_table, " set ", $update_coulmn, "=?", " where user_key = ? and stage_range = ? and ", $update_coulmn, " < ?");
prepare stmt from @query_string;
execute stmt using @clear_score, @user_key, @stage_range, @clear_score2;
deallocate prepare stmt;
END


CREATE DEFINER=`nahyungmin`@`%` FUNCTION `fn_UserStageRecord`($user_key bigint

    , $stage int) RETURNS int(11)
proc_label:BEGIN
 
    declare $stage_range int; #range
    set $stage_range = truncate((($stage - 1/ 30+ 10);
 
    #selectinsert fn.
    if(($user_key % 2= 1) then #odd
        
        #없으면 생성.
        if not exists(select 1 from `user_stage_score_odd` where `user_key` = $user_key and `stage_range` = $stage_range) then
            
            insert into `user_stage_score_odd` (`user_key``stage_range`)
            values ($user_key, $stage_range);
            
        end if;
        
    else #even
        
          #없으면 생성.
        if not exists(select 1 from `user_stage_score_even` where `user_key` = $user_key and `stage_range` = $stage_range) then
        
            insert into `user_stage_score_even` (`user_key``stage_range`)
            values ($user_key, $stage_range);
        
        end if;
        
    end if;
    
    return 1;
    
end
























C#에서는 그냥 조회한 데이터만 반환.

MySqlTable<object> readerList = MySqlManager.ExecuteMySqlTable<object>(ServiceConfig.db_ConnectionString, MySqlProcedureName.sp_UserStageScore, paramList, out Int32 resultCode); responsePacket.ResultNumber = resultCode; if (resultCode == (Int32)ErrorNumbers.SUCCESS) { const Int32 stageCount = 30; for (Int32 i = 0; i < readerList.Count; i++) { for (Int32 j = 0; j < stageCount; j++) { Int32 stage = (stageCount * (Convert.ToInt32(readerList[i, "stage_range"]) - 1)) + j + 1; Int32 score = Convert.ToInt32(readerList[i, string.Format("stage{0}", j + 1)]); responsePacket.UserStageList[stage] = score; } } }


조회 데이터.


CREATE DEFINER=`nahyungmin`@`%` PROCEDURE `sp_UserStageScore`(    

    in $user_key bigint)

proc_label:BEGIN

 

   if(($user_key % 2) = 1) then #odd

        select * from `user_stage_score_odd`

        where `user_key` = $user_key;

    else #even

        select * from `user_stage_score_even` 

        where `user_key` = $user_key;

    end if;

END

'Mysql' 카테고리의 다른 글

Mysql 동적쿼리 결과값 반환  (0) 2019.03.20
Mysql 레코드 값 데이터 대/소문자 구분  (0) 2019.03.13
Mysql 엔진  (0) 2019.03.07
Mysql Update Select  (0) 2019.01.11
Mysql Master Slave 동기화 오류 시 처리  (0) 2018.10.15