Spatial Index - Khi hai điều kiện phạm vi đụng nhau

Tìm kiếm theo vị trí địa lý (bounding box với kinh độ + vĩ độ) tạo ra HAI range condition - B+ tree chỉ tận dụng được MỘT.

Vấn đề

SELECT * FROM businesses
WHERE type = 'restaurant'
  AND longitude BETWEEN -74.0083 AND -73.9752
  AND latitude  BETWEEN  40.7216 AND  40.7422;
 
-- Index (type, longitude, latitude):
--   Bước 1: type='restaurant'     → equality, thu hẹp tốt ✓
--   Bước 2: longitude BETWEEN ... → range, quét ✓
--   Bước 3: latitude BETWEEN ...  → SAU range → KHÔNG thu hẹp được ✗
-- Với dữ liệu cả nước: longitude khớp = hàng triệu dòng
-- → Quét hàng triệu dòng chỉ để lọc latitude → CHẬM

Đây là Nguyên tắc 4 ở dạng không thể né: cả hai chiều đều là range thực sự.

Giải pháp: Spatial Index (R-tree thay vì B+ tree)

Loại index thiết kế riêng cho dữ liệu đa chiều:

-- PostgreSQL: kiểu GEOMETRY + GIST index
CREATE TABLE businesses (
    id BIGINT PRIMARY KEY,
    type VARCHAR(255) NOT NULL,
    location GEOMETRY(Point, 4326) NOT NULL  -- hệ tọa độ WGS 84
);
CREATE INDEX search_idx ON businesses USING GIST (type, location);
 
SELECT * FROM businesses
WHERE type = 'restaurant'
  AND location && ST_MakeEnvelope(-74.0083, 40.7216, -73.9752, 40.7422, 4326);
 
-- MySQL:
CREATE TABLE businesses (..., location POINT SRID 0 NOT NULL);
CREATE SPATIAL INDEX search_idx ON businesses (location);
SELECT * FROM businesses
WHERE type = 'restaurant'
  AND ST_CONTAINS(ST_MakeEnvelope(POINT(...), POINT(...)), location);

Khác biệt PostgreSQL vs MySQL

PostgreSQLMySQL
Nhiều cột trong spatial index✓ (type + location cùng index)✗ (chỉ 1 cột, phải lọc type riêng)
Hệ tọa độ SRID 4326 (độ cong trái đất)✓Một số hàm không hỗ trợ
Khoảng cáchChính xác trên bề mặt cầuMặt phẳng (hơi sai với khoảng cách lớn)

Liên quan