模块课程(3/4)
综合索引和部分索引
在之前的课程中,我们介绍了如何使用索引进行线性 DBMS 查询 (WHERE country = 'Italy')。当我们在两个联合战线上搜索时怎么样?
例如,在真实的电子商务中,我们可能希望找到属于特定客户 ID 并且 属于给定时间范围内的订单:
WHERE customer_id = 90 AND placed_at >= '2025-01-01'。
如果您只有 customer_id 上的基本索引,Postgres 将使用二叉树立即找到客户的 50 个订单,但它必须手动按顺序迭代所有 50 个订单,通过肉眼惰性地过滤日期。
综合指数
我们可以告诉 DBMS 不是沿着单个关键维度,而是沿着多个关键维度对“分析字典”文件进行排序。
CREATE INDEX idx_orders_customer_date ON orders(customer_id, placed_at);“复合”索引将其参数的顺序视为非常重要:这里 B-Tree 节点将 customer_id 严格分组并严格分类在一个块中(最有区别的分离块);它们内部存在子树,该子树以完美排序的顺序以各种 placed_at 时间值分支。
这种结构残酷地消灭了具有多个嵌套谓词的 WHERE 子句。
部分索引(过滤索引)
每个索引都会消耗用户输入流上的磁盘空间和 CPU。 如果电子商务需要不断地排序和检索过滤器,但仅限于少数记录怎么办? (例如:快速轮询未读通知检查。)如果“未读”仅代表其中的 5 个,那么为所有 10,000,000 个通知创建“is_read”索引是非常乏味的。
CREATE INDEX idx_unread_notifs ON notifications(user_id)
WHERE is_read = false; -- Questa aggiuntiva è l'"Indice Parziale"数据库将构建一个快如闪电的 B 树,仅在记录未读时存储对数据库的快速访问密钥!磁盘会爱上 5 行(3 字节)的索引,而不是 1000 万行的索引。快速 SELECT 充分受益:
SELECT * FROM notifications WHERE user_id = 2 AND is_read = false;
轮到你了
我们希望优化临时密码/重置令牌的查找。我们经常进行 SELECT 调用,查找从特定国家/地区和已知城市注册的所有客户。\n在“customers”上创建一个名为“idx_cust_loc”的复合索引。首先传递“国家/地区”字段(更具排他性),然后传递“城市”字段。
显示提示
语法:CREATE INDEX name ON table(col1, col2);
3 次尝试后可用的解决方案
探索条件(部分)索引
优化购物用户查找:用户预先注册,但我们只需要按注册时间顺序列出他们(在“customers”中的“signed_up_on”上创建索引),但仅限于来自确切的全字符串“city”:“Milano”的客户。
显示提示
它通常在目标属性上声明;最后添加魔术关键字 WHERE city = 'Milano'。
3 次尝试后可用的解决方案