Point 공간데이터, 인덱스를 통해 성능 3.5배 개선

Alex·2024년 9월 10일

Binder프로젝트

목록 보기
7/18

MySQL의 공간인덱스 내용을 공부한 것은 여기에 정리해두었다.

SELECT 
	id, 
    created_at, 
    deleted_at, 
    modified_at, 
    address, 
    bookmark_count, 
    dislike_count, 
    image_url, 
    like_count,
    ST_AsText(point, 'axis-order=long-lat') AS point_text,
    title, 
    type
FROM 
    bin
WHERE 
    ST_DISTANCE(point, ST_GeomFromText('POINT(37.4956241314633 127.027722755059)', 4326)) <= 500;

이 쿼리는 인덱스를 탈까?

확인해보니 인덱스를 타지 않았다.

우선, 모든 레코드를 다 풀스캔 하는 방식이다.

시간은 0.1초 정도가 걸린다.

ST_DISTANCE를 사용한 쿼리는 포함관계를 확인하는 것이 아니라, 모든 데이터와 기준점과의 거리를 계산하여 반환하는 쿼리라서 그렇다.

ST_CONTAINS(
        ST_BUFFER(
            ST_GeomFromText('POINT(37.4956241314633 127.027722755059)', 4326), 
            200
        ), 
        point
    );

이렇게 해야 인덱스를 탄다.

시간이 0.09초에서 0.02초로 3.5배정도 개선됐다.
지금은 큰 차이가 없지만, 나중에 요청이 많아지면서 DB 부하가 커지면 성능적으로 더 나은 방식인 것을 체감할 수 있을 것이다.

지금은 데이터가 6000건 안팍인데도 이정도로 줄었으면 상당히 많이 줄어든 것으로 보인다.

트러블슈팅

그런데, 처음에는 저 쿼리를 날려도 인덱스를 타지 않았다.

Point타입에 SRID=4326을 설정해주지 않았기 때문이었다.
SIRD 4326을 해줬는데도 안돼서 보니 내가 인덱스를 직접 걸어주어야 했다.

@Table(
        uniqueConstraints = {
                @UniqueConstraint(
                        name = "sameBin",
                        columnNames = {"address", "type", "title"}
                )
        },
        indexes = {
        @Index(name = "idx_bin_point", columnList = "point")
}
)
public class Bin extends BaseEntityWithSoftDelete {
profile
답을 찾기 위해서 노력하는 사람

0개의 댓글