-- 创建空间索引 CREATE TABLE locations ( id INTPRIMARY KEY, name VARCHAR(50), point POINT NOT NULL, SPATIAL INDEX idx_point (point) );
-- 使用空间索引 SELECT*FROM locations WHERE ST_Distance(point, ST_GeomFromText('POINT(116 40)', 0)) <1000;
四、索引操作
4.1 创建索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
-- 方法1:CREATE INDEX CREATE INDEX idx_name ON users(name); CREATEUNIQUE INDEX idx_email ON users(email); CREATE INDEX idx_age_name ON users(age, name);
-- 方法2:ALTER TABLE ALTER TABLE users ADD INDEX idx_name(name); ALTER TABLE users ADDUNIQUE INDEX idx_email(email); ALTER TABLE users ADD INDEX idx_age_name(age, name);
-- 方法3:创建表时创建 CREATE TABLE users ( id INTPRIMARY KEY, name VARCHAR(50), email VARCHAR(100), INDEX idx_name (name), UNIQUE INDEX idx_email (email) );
-- 原始表结构(无索引) CREATE TABLE orders ( id BIGINTPRIMARY KEY, user_id BIGINT, status INT, amount DECIMAL(10,2), created_at DATETIME, paid_at DATETIME );
-- 添加索引 -- 1. 用户查询自己的订单 ALTER TABLE orders ADD INDEX idx_user_id (user_id);
-- 2. 状态筛选 + 时间排序 ALTER TABLE orders ADD INDEX idx_status_created (status, created_at);
-- 3. 用户 + 状态查询 ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);
-- 4. 金额统计(覆盖索引) ALTER TABLE orders ADD INDEX idx_amount (amount);
-- 优化后的查询 SELECT*FROM orders WHERE user_id =123 AND status =1 ORDERBY created_at DESC LIMIT 20;
9.2 案例:用户表索引优化
1 2 3 4 5 6 7 8 9 10 11 12 13
-- 原始查询(慢) SELECT*FROM users WHERE email ='test@example.com' AND status =1;
-- 分析:email唯一,status需要建索引 -- 添加复合索引 ALTER TABLE users ADD INDEX idx_email_status (email, status);
-- 覆盖索引优化(不需要回表) SELECT id, name, email, status FROM users WHERE email ='test@example.com' AND status =1;
十、常见问题
10.1 索引越多越好吗?
1 2 3 4 5 6 7 8
-- ❌ 错误:每个列都建索引 ALTER TABLE orders ADD INDEX idx_id (id); ALTER TABLE orders ADD INDEX idx_created (created_at); ALTER TABLE orders ADD INDEX idx_amount (amount);
-- ✅ 正确:按需创建,合理规划 -- 分析慢查询,定位高频查询场景 -- 创建复合索引覆盖查询
10.2 为什么索引没生效?
1 2 3 4 5 6 7 8 9 10 11 12
-- 1. 统计信息过期 ANALYZE TABLE table_name;
-- 2. 数据量太少 -- MySQL优化器可能选择全表扫描
-- 3. 索引选择错误 -- 使用 FORCE INDEX 强制使用索引 SELECT*FROM users FORCE INDEX (idx_name) WHERE name ='zhangsan';