복붙노트

[SQL] 시간을 줄이기 위해 선택 MySQL을 다시 쓰기 디스크에 TMP를 작성

SQL

시간을 줄이기 위해 선택 MySQL을 다시 쓰기 디스크에 TMP를 작성

나는 웹 페이지를 작성하는 데 사용으로 매우 좋지 않아 몇 분을 복용 MySQL의 쿼리가 있습니다.

세 개의 테이블이 사용됩니다 poster_data 개별 포스터에 대한 정보가 포함되어 있습니다. poster_categories리스트 모든 종류 (영화, 예술, 등) 동안 posterid 번호가 들어있을 수있는 카테고리 poster_prodcat 목록 하나 개의 포스터는 말, 영화, 인디아나 존스, 해리슨 포드, 모험 영화, 등 여러 줄 것이다

이 느린 쿼리입니다 :

select * 
  from poster_prodcat, 
       poster_data, 
       poster_categories 
 where poster_data.apnumber = poster_prodcat.apnumber 
   and poster_categories.apcatnum = poster_prodcat.apcatnum 
   and poster_prodcat.apcatnum='623'  
ORDER BY aptitle ASC 
   LIMIT 0, 32

에 따르면 설명 :

그것은 몇 분을 복용했다. poster_prodcat이 조금 넘는 1700 만있는 동안 Poster_data는 겨우 80 개 행이 있습니다. poster_prodcat.apcatnum이 = '623'을 40 만에 대한 결과를 가지고하는 동안이와 다른 종류의 쿼리는 거의 눈에 띄지, 디스크에 기록되어있다 선택

해결법

  1. ==============================

    1.당신이 도움이되기를 바랍니다 - http://pastie.org/1105206

    당신이 도움이되기를 바랍니다 - http://pastie.org/1105206

    drop table if exists poster;
    create table poster
    (
    poster_id int unsigned not null auto_increment primary key,
    name varchar(255) not null unique
    )
    engine = innodb; 
    
    
    drop table if exists category;
    create table category
    (
    cat_id mediumint unsigned not null auto_increment primary key,
    name varchar(255) not null unique
    )
    engine = innodb; 
    
    drop table if exists poster_category;
    create table poster_category
    (
    cat_id mediumint unsigned not null,
    poster_id int unsigned not null,
    primary key (cat_id, poster_id) -- note the clustered composite index !!
    )
    engine = innodb;
    
    -- FYI http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html
    
    select count(*) from category
    count(*)
    ========
    500,000
    
    
    select count(*) from poster
    count(*)
    ========
    1,000,000
    
    select count(*) from poster_category
    count(*)
    ========
    125,675,688
    
    select count(*) from poster_category where cat_id = 623
    count(*)
    ========
    342,820
    
    explain
    select
     p.*,
     c.*
    from
     poster_category pc
    inner join category c on pc.cat_id = c.cat_id
    inner join poster p on pc.poster_id = p.poster_id
    where
     pc.cat_id = 623
    order by
     p.name
    limit 32;
    
    id  select_type table   type    possible_keys   key     key_len ref                         rows
    ==  =========== =====   ====    =============   ===     ======= ===                         ====
    1   SIMPLE      c       const   PRIMARY         PRIMARY 3       const                       1   
    1   SIMPLE      p       index   PRIMARY         name    257     null                        32  
    1   SIMPLE      pc      eq_ref  PRIMARY         PRIMARY 7       const,foo_db.p.poster_id    1   
    
    select
     p.*,
     c.*
    from
     poster_category pc
    inner join category c on pc.cat_id = c.cat_id
    inner join poster p on pc.poster_id = p.poster_id
    where
     pc.cat_id = 623
    order by
     p.name
    limit 32;
    
    Statement:21/08/2010 
    0:00:00.021: Query OK
    
  2. ==============================

    2.나열된 쿼리는 최종 쿼리가 모양을 어떻게? (그들은 apcatnum = / ID를 가지고 그래서 /?)

    나열된 쿼리는 최종 쿼리가 모양을 어떻게? (그들은 apcatnum = / ID를 가지고 그래서 /?)

    여기서 poster_data.apnumber = poster_prodcat.apnumber 및 poster_categories.apcatnum = poster_prodcat.apcatnum 및 poster_prodcat.apcatnum = '623'

    poster_prodcat.apcatnum = '623' 크게 데이터 세트 MySQL이에 일해야 감소, 따라서이 쿼리의 첫 번째 구문 분석 된 부분이되어야한다.

    그런 곳-비교를 교환하기 위하여 계속 데이터 세트 가장 먼저 구문 분석됩니다 최소화하는 그래서.

    또한 하위 쿼리를 시도 할 수 있습니다. 나는 의지 도움말하지만, MySQL은 아마 처음 3 개 테이블을받지 않습니다 만, 먼저 서브 쿼리하고 다른 하나를 모르겠어요. 조회하면서 메모리 소모를 최소화한다. 당신이 정말로 모든 열을 선택하려면 (당신은 *이 사용하고있는대로)이 옵션을 선택하지 않습니다 만.

  3. ==============================

    3.당신은 POSTER_DATA에서 apnumber에 인덱스가 있어야합니다. 841152 개 기록을 검사하면 성능을 죽이는 것입니다.

    당신은 POSTER_DATA에서 apnumber에 인덱스가 있어야합니다. 841152 개 기록을 검사하면 성능을 죽이는 것입니다.

  4. ==============================

    4.쿼리처럼 보인다는 순서를 얻기 위해 apptitle 인덱스를 사용하고 있지만, 결과를 필터링하는 전체 검사를하고있다. 난 당신이 poster_data에 모두 apptitle 및 apnumber에서 복합 인덱스가 있다면 도움이 될 것 같아요. MySQL은 다음 정렬 순서 및 필터 두 가지를 모두 수행하려면이 옵션을 사용할 수 있습니다.

    쿼리처럼 보인다는 순서를 얻기 위해 apptitle 인덱스를 사용하고 있지만, 결과를 필터링하는 전체 검사를하고있다. 난 당신이 poster_data에 모두 apptitle 및 apnumber에서 복합 인덱스가 있다면 도움이 될 것 같아요. MySQL은 다음 정렬 순서 및 필터 두 가지를 모두 수행하려면이 옵션을 사용할 수 있습니다.

    create index data_title_anum_idx on poster_data(aptitle,apnumber);
    
  5. from https://stackoverflow.com/questions/3534597/rewriting-mysql-select-to-reduce-time-and-writing-tmp-to-disk by cc-by-sa and MIT license