2011-03-18 5 views
0

나는 두 개의 테이블이있다. 나는 9 개 게임 검색하려고 :와최적화 MySQL의 임의 쿼리

  • 1 무작위로 게임을 "doublepoints"META
  • 3 개 최신 게임 "프리미엄"META
  • 1 랜덤 게임 META
  • 1 무작위로 게임을 "특색" (added_at DESC BY ORDER) 내가 그 일을 꽤 까다로운 시스템이 현재로서는

위의 6 게임 중 하나없는

  • 3 랜덤 게임, 그것은 더 (을)를 본다 R 덜이 같은 :

    SELECT FLOOR(RAND() * (COUNT(*) - " . ($count - 1) .")) AS `offset` 
    FROM table_meta WHERE meta = '{$meta}' 
    
    SELECT t1.* FROM table_meta t2 
    LEFT JOIN table_game t1 ON t1.id = t2.id_game 
    WHERE t2.meta = '{$meta}' LIMIT {$offset}, {$count} 
    

    이 (gameRandom 매우 유사하다) 당신이 볼 수 있듯이이 내 제한을 무시 : 순간

    $feat = getGameMetaRandom(1, 'featured'); 
    $prem = getGameMetaRandom(1, 'premium'); 
    $dubl = getGameMetaRandom(1, 'doublepoints'); 
    $last = getGameLatest(3); 
    $rand = getGameRandom(3); 
    

    임의 기능 (getGameMetaRandom($count, $meta);에서) 두 개의 질의를한다 위의 6 개 게임 중 하나가 아니며이 모든 것은 9 개의 검색어를 사용하며 임의 화는 실제로 무작위가 아닙니다.

    그래서 나의 세 가지 목표와 내 가능한 해결 방법은 다음과 같습니다

    1. 3 개 무작위로 게임을하는 방법 aforeselected 게임 중 하나를 반복하지. 처음 6 개의 게임을 선택한 후에는 ID를 나열하고 NOT IN()으로 마지막 쿼리에서 사용할 수 있지만 지나치게 최적화되지는 않습니다.
    2. 랜덤 테이크 게임을 랜덤하게 만드는 방법, 랜덤 옵셋을 선택하지 않고 n 게임을 즐기는 방법은 무엇입니까? 분명히 ORDER BY RAND()를 사용하고 있지만 테이블에 수백 개의 행이 있으면 차이가 발생하지 않는 한 실제로 느린 것에 대해 정말 들었습니다.
    3. 쿼리 수를 줄이는 방법은 무엇입니까? 일에 첫 번째 세 개의 쿼리, 나는 5 개 쿼리 왼쪽하고 그룹 또는 RAND에 의해 순서를 사용하여() 내가 처음 "검색 오프셋"쿼리를 무시할 수 SELECT t1.* FROM table_meta t2 LEFT JOIN table_game t1 ON t1.id = t2.id_game WHERE t2.meta = '{$meta}' ORDER BY RAND() LIMIT {$count}

    하지만 여전히, thiese 같은 것을 함께 할 것입니다 일반적으로 RAND() ORDER BY RAND()를 사용해야합니다. 일부 테스트에서 보면 속도가 너무 느려 보입니다. 더 많은 것을 향상시키기위한 힌트가 있습니까?

  • +0

    세 가지 질문이 있으며 직접 또는 사소한 질문이 없습니다 ... – RichardTheKiwi

    +0

    @ 리차드 일컬어 사이버 스키 : 나는 .. 추측합니다. 문제를 더 쉽게 고려할 수있는 경우 가능한 해결책과 우려 사항을 추가했습니다. 저는 MySQL에서 초보자이며 거의 아무것도 알지 못합니다. – Maurycy

    답변

    1

    게임 테이블 :

    [email protected] [kris]> show create table games\G 
    *************************** 1. row *************************** 
         Table: games 
    Create Table: CREATE TABLE `games` (
        `id` int(11) NOT NULL AUTO_INCREMENT, 
        `flags` enum('features','premium','doublepoints') NOT NULL, 
        `added_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
        PRIMARY KEY (`id`) 
    ) ENGINE=InnoDB AUTO_INCREMENT=8184 DEFAULT CHARSET=latin1 
    1 row in set (0.00 sec) 
    

    샘플 게임 :

    [email protected] [kris]> insert into games values (NULL, floor(rand() * 4), now() - interval 1200 second); 
    Query OK, 1 row affected, 1 warning (0.00 sec) 
    
    Note (Code 1592): Statement may not be safe to log in statement format. 
    

    더 많은 샘플 게임 : 문 위의

    [email protected] [kris]> insert into games select NULL, floor(rand() * 4), now() - interval 1200 second from games; 
    Query OK, 1 row affected, 1 warning (0.00 sec) 
    Records: 1 Duplicates: 0 Warnings: 0 
    
    Note (Code 1592): Statement may not be safe to log in statement format. 
    

    반복, 충분한 샘플 데이터까지. 데이터 잘림 경고는 무시할 수 있습니다.이 플래그는 enum() 열에 0을 삽입하여 유령이없는 게임을 만들어내는 아티팩트이며, 이는 우리가 원하는 것입니다.

    [email protected] [kris]> create table shuffle like games; 
    Query OK, 0 rows affected (0.09 sec) 
    
    [email protected] [kris]> alter table shuffle modify column id integer not null, drop primary key, add column shuffleid integer not null auto_increment, add primary key (shuffleid), add index(flags), add index(added_at), add index(id); 
    Query OK, 0 rows affected (0.13 sec) 
    Records: 0 Duplicates: 0 Warnings: 0 
    

    이 게임 셔플 :

    [email protected] [kris]> select count(*) from games; 
    +----------+ 
    | count(*) | 
    +----------+ 
    |  8192 | 
    +----------+ 
    1 row in set (0.00 sec) 
    

    우리는 게임의 단행 목록을 만들

    [email protected] [kris]> insert into shuffle select id, flags, added_at, NULL from games order by rand(); 
    Query OK, 8192 rows affected, 1 warning (0.34 sec) 
    Records: 8192 Duplicates: 0 Warnings: 0 
    
    Note (Code 1592): Statement may not be safe to log in statement format. 
    

    이제 단순히 당신이 필요로 가져 오기 :

    [email protected] [kris]> select min(id) as id from shuffle where flags = 'premium' 
        union all select min(id) from shuffle where flags = 'features' 
        union all select min(id) from games where flags = 'doublepoints' 
        union all (select id from shuffle order by added_at limit 3); 
    +------+ 
    | id | 
    +------+ 
    | 8216 | 
    | 8214 | 
    | 8218 | 
    | 8213 | 
    | 8214 | 
    | 8216 | 
    +------+ 
    6 rows in set (0.00 sec) 
    

    그것은 더 3 개의 임의의 행을 효율적으로 선택

    [email protected] [kris]> select id from shuffle where id not in (8216, 8214, 8218, 8213, 8214, 8216) limit 3; 
    +------+ 
    | id | 
    +------+ 
    | 8215 | 
    | 8219 | 
    | 8220 | 
    +------+ 
    3 rows in set (0.00 sec) 
    

    그런 다음 테이블의 후속 사용이 9 개 새로운 가치를 생성 할 수 있도록, 셔플에서 9 개 값을 삭제 (또는 3 가장 최근 thingies를 떠나 : 두 번째 쿼리에서 위의 세트에없는 S 에서, 당신이 좋아하는 경우).