0

두 개의 테이블 -과 images이 있습니다. books 테이블에는 id (기본 키), name (고유하지 않음), releasedate 등 많은 열이 있습니다. images 테이블에는 id 두 개의 열이 있습니다 (고유하지 않습니다. 즉, 하나의 책 ID는 그리고이 모든 이미지가 필요합니다.이 열은 고유하지 않은 색인을가집니다.) poster (고유 한 기본 키이며 모든 이미지는 동일한 버킷에 있으므로 중복 된 이름을 가질 수 없습니다). 내 요구 사항에는 책 이름이 주어지며 모든 이미지가 릴리스 된 연도와 함께 표시되며 각 이미지의 경우 bucketname이고이 경우 숫자는 bucketname입니다. id 2와 함께 한 - 당신이 볼 수 있듯이주어진 유스 케이스를위한 최적의 MySQL 테이블 스키마

enter image description here

두 개의 일치하는 검색 결과가 있습니다 :

select books.id,poster,bucketname,year(releasedate) from books 
inner join images where images.bookId = books.id and books.name = "<name>"; 

샘플 결과 집합은 다음과 같이 보일 수 있습니다 :

나는이 쿼리를 실행하고 year 1989 년, 5 개의 이미지가 있고 다른 하나는 id 261009, year 2013 및 이미지 1 개가 있습니다.

문제는 쿼리가 매우 느립니다. MySQL 콘솔 자체에서 영 (zero)로드가 발생하면 약 14 초가 걸립니다 (프로덕션 환경에서는 여러 개의 동시 요청이있을 수 있으며 큐에 대기하여 지연 될 수 있음). 이는 자동 완성에서 용납되지 않습니다. 누구든지 올바른 인덱스/키를 테이블에 추가하여 쿼리를 최적화하는 방법을 알려 줄 수 있습니까? MySQL에서 가능하지 않은 경우 적절한 Redis 스키마와 관련된 제안도 유용 할 것입니다.

편집 : 약식 번호. images - 480k의 행이 books - 285k에 있습니다. 앞으로는 autocomplete가 책의 저자뿐만 아니라 책의 이름에 대한 결과를 보여줄 것이므로 검색어는 도서와 마찬가지로 별도의 테이블 authors을 가져와 각 저자의 이름은 idname입니다.

답변

1

최적의 성능을 위해 적합한 커버 인덱스를 사용할 수 있습니다. 예를 들어 :

... on `books` (`name`,`id`,`releasedate`) 
... on `images` (`bookid`,`poster`,`bucketname`) 

우리 때문에 WHERE 절에서 평등 술어의 인덱스의 선두 컬럼으로 name를 원한다. 우리는 인덱스를 "커버 인덱스"로 만들기 위해 인덱스에 포함 된 id와 release를 원하므로 값을 검색하기 위해 기본 테이블의 페이지를 방문 할 필요없이 인덱스에서 쿼리를 만족시킬 수 있습니다.

ON 절의 참조로 인해 bookid을 맨 앞줄로 사용하려고합니다. 다시 말하지만, 색인에서 바로 posterbucketname을 사용 가능하게하면 "포함"색인이됩니다. 쿼리 실행 계획을 보려면 EXPLAIN을 사용하십시오.

images에 일치하는 행이 없으면 내부 조인 작업에서 books의 행을 반환하지 않습니다. 사용할 수있는 이미지가 없을 때에도 books에서 행을 반환하려는 경우 외부 조인을 사용할 수 있습니다.

SELECT b.id 
    , i.poster 
    , i.bucketname 
    , YEAR(b.releasedate) 
    FROM books b 
    LEFT 
    JOIN images i 
    ON i.bookid = b.id 
WHERE b.name = ? 
+0

감사 :

나는 이런 식으로 쿼리를 작성할 것입니다.내 테이블 예제와 관련하여 커버 인덱스의 전체 구문을 제공 할 수 있습니까? 그리고 기존의 키와 인덱스 위에 올려 놓았습니까? – SexyBeast

+0

예 : **'도서 \'(\'이름 \', \'아이디 \', \'출시 된 \')에 대한 색인 생성''book_IX4 \''**'. 기존 인덱스와 함께 추가 할 수 있습니다. 이 새로운 색인은 기존 색인이 고유성을 강화하는 데 사용되지 않는 한'name' 열에 대한 색인을 중복되게 만듭니다. 즉,'name'에 인덱스를 사용할 수있는 모든 쿼리는 세 개의 컬럼에 대한 인덱스를 사용할 수 있습니다. 왜냐하면'name'이 선행 컬럼이기 때문입니다. – spencer7593

+0

전능하신 주님, 그것은 .00087 초 걸렸습니다! 고마워 친구! 한가지 질문으로'images' 테이블에'poster'를 포함하는 커버 링 키를 추가하는 반면'poster' 자체는 이미 기본 키입니다. 이로 인해 많은 공간을 차지하거나 삽입 속도가 느려지는 것과 같은 문제가 발생합니까? – SexyBeast