2017-11-27 10 views
2

나는 약 600.000 개의 엔트리가있는 테이블을 가지고 있으며 몇개의 매우 구체적인 엔트리를 업데이트해야합니다. 표는 다음과 같습니다.MySQL이 인덱스 위에 기본 키를 선택했습니다.

(start, end, room_id)로 색인을 생성하여 SELECT 쿼리에 큰 성능 향상을 가져 왔습니다. 그러나 지금은 다음 쿼리를 실행 해요 :

update vacancies 
    set locked = 1 
    where start >= '2017-11-28 22:00:00' 
     and end <= '2017-11-28 23:00:00' 
     and (room_id = 1234 
      or room_id in (select other_room 
        from room_dependencies 
        where first_room = 1234)) 

내가이 쿼리는 (~이 1.5 초를) 무엇을하고 있는지에 대한 상당한 시간이 많이 걸립니다 있다고 생각합니다. (FTS를

EXPLAIN results

나는 DB 전문가 (지금까지) 아니지만, 나는이 쿼리는 전체 테이블 스캔을 실행하는 것을 이상하다고 생각 : 나는이 MySQL을 EXPLAIN 커맨드를 실행하고 다음과 같은 반환) 대신 INDEX (start, end, room_id)를 사용하십시오. 분명히 "시작"을 실행 가능한 키로 식별하고 무시한 다음 PRIMARY KEY를 선택하고 FTS를 실행합니다. 따라서 this answer을 따라 PRIMARY KEY를 제거하고 새로운 PRIMARY KEY로 (start, end, room_id)를 추가했지만 결과는 정확히 동일하거나 최악이었습니다.

이것은 플랫폼에서 다른 작업을 수행 한 직후에 수행해야하는 단일 요청이므로 대기열에 넣고 지연된 형태로 업데이트 된 다른 항목과 함께 배치로 실행할 수 없습니다.

이 쿼리의 성능을 향상시킬 수있는 다른 방법이 있습니까?

감사합니다.

+0

다른 선택 항목은 어떻게 생겼습니까? 일반적으로 범위를 원하는 열을 다중 열 인덱스 끝에 지정합니다 (room_id, start, end). 방금 room_id에 추가 색인이 필요하다고 생각됩니다. 혹은'update vacancies index (start) set ...를 사용하라 '는 말은 아마도 충분할 것이다. – ysth

+0

(작은 글자 뒤에 의미가없는 '1') – Strawberry

+1

시작 시간이 '= 2017-11-28 22:00:00'인 행 수는 얼마나됩니까?'어디에서 시작> = '2017-11-28 22:00:00'을 시도하고 <2017-11-28 23:00:00 '을 시작하고 <='2017-11-28 23:00:00 끝내셨습니까? '그리고 ...'? 옵티마이 저는 원하는 종료 시간 이후에 시작하는 행을 제거 할 수 있다는 것을 직관적으로 이해하지 못합니다. –

답변

0

MySQL in 조건은 인덱스를 이용하지 않습니다. 대신 inner join을 시도하십시오.

update vacancies 
    inner join 
    (select other_room 
      from room_dependencies 
      where first_room = 1234) t2 
    on vacancies.room_id = t2.other_room 
    set locked = 1 
    where start >= '' 
      and end <= ''; 

room_id = 1234만으로 다른 업데이트를 수행하십시오.

0

범위가 인덱스에서 2 개의 개별 속성으로 표시되기 때문에 시작 및 끝 값이 작은 수를 지정하는 반면 DBMS는 먼저 start >= '2017-11-28 22:00:00' 인 모든 단일 색인 항목을 읽어야 만 end <= '2017-11-28 23:00:00'을 만족하십시오. DBMS는이 작업이 값 비싼 작업이라는 것을 알고 있습니다.

이 문제를 해결하는 데는 2 가지 경로가 있습니다. 하나는 미리 정의 된 블록 세트에서 범위를 나눈 다음 이들 블록을 공석 테이블에 다시 연결하는 것입니다 (이는 지저분하지만 여전히 효율적이지는 않습니다).

올바른 해결책은 시간을 1 차원 공간으로 처리하고 geo-spatial indexing을 적용하는 것입니다. MySQL에서 지리 공간 좌표는 2 차원 만 가질 수 있으므로 시간 범위를 2D 공간으로 매핑해야합니다. 이 작업을 수행하는 방법에 대한 인터넷상의 예제가 많이 있지만, MySQL과 날짜 범위와 관련하여 특별히 보지 못했습니다. 다음은 using SQL Server의 예입니다.

시간당 객실을 임대한다는 점에 주목하십시오!