4.4 KiB
4.4 KiB
06 索引策略与典型查询模式
本节从“页面/接口会怎么查”出发解释索引的设计意图,并给出可复用的查询模式。
1. 索引总体思路
从 complete_mall_database.sql / mall_migration.sql 中可以看到索引集中在:
- 列表页高频过滤字段:
status、created_at、merchant_id、user_id、category_id - 对外访问字段:
cid、slug - 排序/榜单字段:
sale_count、rating_avg、rating_count、base_price - 多值字段:
tags(GIN)
其核心理念是:
- 读路径优先:电商最常见的是“列表页 + 详情页”,索引优先覆盖这些路径。
- SEO 友好:对外 URL 常用
cid/slug,因此为其建索引。 - 避免重计算:用触发器维护汇总字段(库存/销量),让查询尽量落在单表或轻量 join。
2. 典型查询模式与对应索引
注:以下 SQL 示例以可读性为主,实际项目可能通过视图(如
ml_products_detail_view)或 API 层封装。
2.1 商品列表页(按分类 + 上架状态 + 时间倒序)
典型查询:
select id, cid, name, base_price, main_image_url, sale_count, rating_avg
from public.ml_products
where category_id = '...category_uuid...'::uuid
and status = 1
order by created_at desc
limit 20 offset 0;
依赖索引:
idx_ml_products_category(category_id, status)idx_ml_products_status(status, created_at desc)
2.2 商品列表页(商家后台:按商家 + 状态)
select id, cid, name, status, total_stock, sale_count
from public.ml_products
where merchant_id = '...merchant_uuid...'::uuid
order by updated_at desc
limit 50;
依赖索引:
idx_ml_products_merchant(merchant_id, status)(也会被 merchant_id 过滤利用)
2.3 商品详情页(按 cid 或 slug)
-- 方式 1:cid
select * from public.get_product_by_cid(12345);
-- 方式 2:slug
select *
from public.ml_products
where slug = 'iphone-15-pro' and status = 1;
依赖索引:
idx_ml_products_cid(cid)idx_ml_products_slug(slug)
2.4 商品搜索/筛选(按 tags)
select id, cid, name
from public.ml_products
where status = 1
and tags @> array['手机','苹果']::text[]
order by sale_count desc
limit 20;
依赖索引:
idx_ml_products_tags using gin(tags)
说明:
tags @> array[...]是典型的 GIN 可加速模式。
2.5 订单列表(用户维度)
select id, order_no, total_amount, order_status, created_at
from public.ml_orders
where user_id = '...user_uuid...'::uuid
order by created_at desc
limit 20;
依赖索引:
idx_ml_orders_user(user_id, created_at desc)
2.6 订单列表(商家维度)
select id, order_no, total_amount, order_status, created_at
from public.ml_orders
where merchant_id = '...merchant_uuid...'::uuid
order by created_at desc
limit 20;
依赖索引:
idx_ml_orders_merchant(merchant_id, created_at desc)
2.7 订单按状态过滤(运营/商家后台常见)
select id, order_no
from public.ml_orders
where order_status in (1,2,3)
order by created_at desc
limit 50;
依赖索引:
idx_ml_orders_status(order_status, created_at desc)
2.8 购物车加载
select c.*, s.price, p.name
from public.ml_shopping_cart c
left join public.ml_product_skus s on s.id = c.sku_id
left join public.ml_products p on p.id = c.product_id
where c.user_id = '...user_uuid...'::uuid
order by c.updated_at desc;
依赖索引:
idx_ml_shopping_cart_user(user_id)
3. JSONB 字段的索引缺口(建议项)
当前脚本对 tags 做了 GIN,但对以下 JSONB 的查询与索引没有“强约束”体现:
ml_orders.shipping_addressml_shops.address/business_hoursml_coupon_templates.applicable_products/categories
如果业务上出现以下高频查询:
- “按城市/区域筛选订单/店铺”
- “某个商品可用哪些券”
建议考虑:
- 关系化建模(反向关联表)
- 或表达式索引(例如对 JSONB 内部字段建索引)
4. 索引维护建议
- 新增字段/查询前先用
EXPLAIN (ANALYZE, BUFFERS)验证是否命中索引。 - 避免为低选择性字段(如
status单列)盲目建索引,优先组合索引匹配真实查询。 - 注意 RLS 会影响执行计划与开销,常用过滤字段建议都具备索引(
user_id/merchant_id/status/created_at)。