2013-10-25 1 views
2

정규화 된 데이터베이스 구조가 있으므로 설명하려고합니다.내 SQL 테이블에 적용 할 색인이 무엇인지 확실하지 않습니다.

3 테이블 :

  • 프로파일
  • 키워드
  • keyword_profile

내 웹 사이트에 대한 모든 프로필은 연결된 키워드의 다양한 수를 가질 수있다. 모든 키워드는 키워드 표에서 ID 번호를 얻습니다. 모든 프로파일은 프로파일 테이블에서 ID 번호를 얻습니다. keyword_profile 테이블에는 profileID에 연결된 keywordID가있는 약 600,000 개의 행이 있습니다.

프로필 테이블의 ID 열에 PRIMARY 인덱스가 있습니다.
키워드 표의 ID 열에 PRIMARY 색인이 있습니다.
키워드 표의 내 키워드 이름 열에 UNIQUE 색인이 있습니다.
나는이 같은 keyword_profile 테이블에 PRIMARY 인덱스가 (PROFILE_ID, keyword_id는)
나는 keyword_profile 테이블

다음의 PROFILE_ID 컬럼에 인덱스가 : 나는 다음과 같은 쿼리를 실행할 때 (특정 키워드입니다 'dienst') :

EXPLAIN SELECT profiles.hoofdrubriek, profiles.plaats, profiles.bedrijfsnaam, profiles.gemeente, profiles.bedrijfsslogan, profiles.straatnaam, profiles.huisnummer, profiles.postcode, profiles.telefoonnummer, profiles.fax,profiles.email, profiles.website, profiles.bedrijfslogo 
FROM profiles 
INNER JOIN profile_dienst ON profiles.ID = profile_dienst.profile_id 
INNER JOIN diensten ON profile_dienst.dienst_id = diensten.ID 
WHERE (
diensten.dienst = 'Aannemersdiensten' 
) 
ORDER BY profiles.grade DESC , profiles.bedrijfsnaam 

다음과 같은 결과가 나타납니다. 그것은 모든 600k 행을 검사합니다 !! 그게 내가 원하는 결과는 아니야. 내가 적용 할 수있는 인덱스는 무엇일까? 그러면 테이블 전체를 스캔하지 않을 것이다.

id - select_type - table - type - key - rows - Extra 
1 - SIMPLE - diensten - const - dienst - 1 - Using temporary; Using filesort 
1 - SIMPLE - profile_dienst - index - PRIMARY - 662000 - Using where; Using index 
1 - SIMPLE - profiles - eq_ref - PRIMARY - 1 - Using where 

도움 주셔서 감사합니다 !!

편집 : 추가 SHOW CREATE TABLE 결과 :

CREATE TABLE `diensten` (
`ID` mediumint(9) NOT NULL AUTO_INCREMENT, 
`dienst` varchar(255) NOT NULL, 
PRIMARY KEY (`ID`), 
UNIQUE KEY `dienst` (`dienst`) 
) ENGINE=MyISAM AUTO_INCREMENT=1903 DEFAULT CHARSET=utf8 


CREATE TABLE `profile_dienst` (
`profile_id` varchar(20) NOT NULL, 
`dienst_id` varchar(20) NOT NULL, 
PRIMARY KEY (`dienst_id`,`profile_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

CREATE TABLE `profiles` (
`ID` varchar(255) NOT NULL DEFAULT '', 
`username` varchar(255) DEFAULT NULL, 
...more columns..., 
    `grade` int(5) NOT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `IDX_TIMESTAMP` (`timestamp`), 
    KEY `IDX_NIEUW` (`nieuw`), 
    KEY `IDX_HOOFDRUBRIEK` (`hoofdrubriek`), 
    KEY `bedrijfsnaam` (`bedrijfsnaam`), 
    KEY `grade` (`grade`), 
    KEY `gemeente` (`gemeente`), 
    KEY `plaats` (`plaats`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 
+0

'(profile_id, dienst_id)와'(dienst_id, profile_id)'연관 테이블에서? –

+0

그리고'dienst'에 대한 색인은'diensten' 테이블에 있습니까? –

+0

영어 이름과 네덜란드 이름 사이에 약간의 혼란이 있다고 생각합니다. 나는 키워드를 대체 할 수 있다고 생각한다. – mucio

답변

0

나는 그것이 좋은 생각, 그것은 MySQL을가 diensten.ID을 찾아하기 때문에 스캔이 profile_dienst의 모든 값을 생각합니다. 좋은 소식은 그것을 사용하고 색인입니다.

당신은 여기에 MySQL을 설명 할 계획의 추가 컬럼에 대한 자세한 정보를 확인할 수 있습니다 EXPLAIN Extra Information 당신은 당신이 MEDIUMINT의 profile_dienst.dienst_id와 함께 varrhar (20)를 합류 .. 정상화 더 할 필요가

+0

동의 할 수 없습니다. 비록 인덱스를 사용하고 있지만, 연관 테이블이 24mln + 행 인 키워드 유형도 있습니다. 인덱스가 있더라도 너무 느리게 실행됩니다. – user2704687

+0

너무 느린가요? 인덱스 된 열의 숫자 유형입니까? – mucio

+0

너무 느리다는 것은 페이지가로드되는 데 약 10 초 이상 걸린다는 것을 의미합니다. number-id 만있는 열은 모두 중간 값 (9)입니다. 프로파일 ID에는 숫자와 문자가 모두 있으며 숫자는 varchar (20) – user2704687

0

= diensten .ID thats 왜 전체 인덱스 스캔이 필요한지 설명합니다. 인덱스 열과 엑스트라 : "인덱스 사용"은 의미합니다. MySQL은 데이터 유형이 동일하면 인덱스 만 사용할 수 있습니다.

작은 데모와 내부 self join http://sqlfiddle.com/#!2/1ef09/4 MySQL이 인덱스를 사용할 수있는 경우 .. INT, SMALLINT, CHAR 및 VARCHAR 데이터 유형이 사용되었습니다. 여기에서 JOIN ON 및 INT 및 SMALLINT가 인덱스 및 JOIN을 사용할 수 있음을 볼 수 있습니다. CHAR과 VARCHAR도 ..하지만 INT와 CHAR을 섞는다 MySQL은 인덱스를 사용할 수없고 전체 테이블 스캔이 필요하다. TYPE : ALL

관련 문제