Files
medical-mall/docs/sql/06_indexes_and_query_patterns.md

180 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 商品列表页(按分类 + 上架状态 + 时间倒序)
典型查询:
```sql
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 商品列表页(商家后台:按商家 + 状态)
```sql
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
```sql
-- 方式 1cid
select * from public.get_product_by_cid(12345);
-- 方式 2slug
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
```sql
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 订单列表(用户维度)
```sql
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 订单列表(商家维度)
```sql
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 订单按状态过滤(运营/商家后台常见)
```sql
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 购物车加载
```sql
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_address`
- `ml_shops.address/business_hours`
- `ml_coupon_templates.applicable_products/categories`
如果业务上出现以下高频查询:
- “按城市/区域筛选订单/店铺”
- “某个商品可用哪些券”
建议考虑:
- 关系化建模(反向关联表)
- 或表达式索引(例如对 JSONB 内部字段建索引)
---
## 4. 索引维护建议
- 新增字段/查询前先用 `EXPLAIN (ANALYZE, BUFFERS)` 验证是否命中索引。
- 避免为低选择性字段(如 `status` 单列)盲目建索引,优先组合索引匹配真实查询。
- 注意 RLS 会影响执行计划与开销,常用过滤字段建议都具备索引(`user_id/merchant_id/status/created_at`)。