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 {