MySQL 이이 간단한 조인 쿼리에서 사용할 '명백한'키를 무시하는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/804258

  •  03-07-2019
  •  | 
  •  

문제

나는 간단한 쿼리라고 생각했지만 '영원히'필요가 있습니다. 나는 SQL 최적화에 좋지 않으므로 여러분에게 물어볼 수 있다고 생각했습니다.

설명과 함께 다음은 다음과 같습니다.

EXPLAIN SELECT *
    FROM `firms_firmphonenumber`
    INNER JOIN `firms_location` ON (
        `firms_firmphonenumber`.`location_id` = `firms_location`.`id`
    )
    ORDER BY
         `firms_location`.`name_en` ASC,
         `firms_firmphonenumber`.`location_id` ASC LIMIT 100;

결과:

id, select_type,       table,           type,  possible_keys,                     key,                           key_len, ref, rows, Extra
1,  'SIMPLE',     'firms_location',    'ALL',  'PRIMARY',                        '',                            '',             '', 73030, 'Using temporary; Using filesort'
1,  'SIMPLE', 'firms_firmphonenumber', 'ref', 'firms_firmphonenumber_firm_id', 'firms_firmphonenumber_firm_id', '4', 'citiadmin.firms_location.id', 1, ''

CORMS_LOCATION의 키 :

Keyname                 Type    Unique  Packed  Field   Cardinality
PRIMARY                    BTREE    Yes     No      id      65818
firms_location_name_en     BTREE    No      No      name_en 65818

CORMS_FIRMPHONENUMBER의 키 :

Keyname                     Type  Unique Packed  Field       Cardinality
PRIMARY                         BTREE Yes    No      id          85088
firms_firmphonenumber_firm_id   BTREE No     No      location_id 85088

MySQL이 Comporms_Location 테이블의 기본 키 사용을 거부하는 것처럼 보이지만 이유는 모르겠습니다.

모든 도움이 될 것입니다 많이 감사합니다.


솔루션이 게시 된 후 편집

변경된 순서로 :

EXPLAIN SELECT *
    FROM `firms_firmphonenumber`
    INNER JOIN `firms_location` ON (
        `firms_firmphonenumber`.`location_id` = `firms_location`.`id`
    )
    ORDER BY
         `firms_location`.`name_en` ASC,
         `firms_location`.id ASC LIMIT 100;
         #`firms_firmphonenumber`.`location_id` ASC LIMIT 100;

결과:

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
1,"SIMPLE","firms_location","index","PRIMARY","firms_location_name_en","767","",100,""
1,"SIMPLE","firms_firmphonenumber","ref","firms_firmphonenumber_firm_id","firms_firmphonenumber_firm_id","4","citiadmin.firms_location.id",1,""

왜 지금 이것을 사용하기로 결정 했습니까? MySQL은 몇 가지 이상한 선택을합니다 ... 모든 통찰력은 다시 도움이 될 것입니다 :)


Django의 세부 사항으로 편집하십시오

원래, 나는 (약식) 모델을 가지고있었습니다.

class Location(models.Model):
    id = models.AutoField(primary_key=True)
    name_en = models.CharField(max_length=255, db_index=True)
    class Meta:
        ordering = ("name_en", "id")

class FirmPhoneNumber(models.Model):
    location = models.ForeignKey(Location, db_index=True)
    number = PhoneNumberField(db_index=True)
    class Meta:
        ordering = ("location", "number")

Locaion의 클래스 메타를 변경합니다 ("name_en", ) 가짜 명령을받지 않도록 쿼리를 수정했습니다.

도움이 되었습니까?

해결책

이러한 것들은 시행 착오에 의한 경향이 있지만 comporms_firmphonenumber.location_id가 아닌 comporms_location.id에서 주문하십시오. 그것들은 같은 값이지만 MySQL은 인덱스를 선택할 수 있습니다.

다른 팁

조인을 위해 그것을 사용하고 있습니다. 그게 그게 'citiadmin.firms_location.id' 값의 가치 ref 열. 표시되지 않습니다 possible_keys 그리고 key 위치가없는 곳이없고 키를 반영하기 때문에 주문별로 주문할 수 있습니다.

쿼리 속도를 높이려면 인덱싱을 시도하십시오. name_en.

위치가없고 결합 필드의 카디널리티가 결합 필드보다 높기 때문에 모든 것을 얻을 수 있다고 계산합니다. 결합에서 인덱스를 사용하면 속도가 높아지지 않으므로 정렬을 위해 인덱스 사용의 최적화가 줄어 듭니다.

먼저, 지정한 인덱스를 사용하도록 강제로 사용할 수 있습니다. 또한, 카디널리티가 올바르게 추정되도록 최적화를 시도하십시오. (나는 당신이 일련의 임의의 "다이브"로 추정하는 inno를 사용하고 있다고 생각합니다. 이것이 실제로 알고 있다면, 카디널리티가 왜 그렇게 보이는지 궁금합니다.)

이름 등을 색인화하지 마십시오. MySQL은 조인기 당 테이블 당 하나의 인덱스 만 사용하면 인덱스가 대량으로 올라갑니다.

얼마나 많은 데이터? 몇 줄 만 있으면 대부분의 데이터베이스는 어떤 색인이 있는지에 관계없이 테이블 스캔을 수행합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top