AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79590141
Accepted
Andrus
Andrus
Asked: 2025-04-24 16:36:28 +0800 CST2025-04-24 16:36:28 +0800 CST 2025-04-24 16:36:28 +0800 CST

如果搜索值中使用了修剪,如何使用索引进行搜索

  • 772

我的 Postgres 17 数据库有一个大表,其中有 245 列,其中包含一个索引列ribakood:

CREATE TABLE firma2.toode
(
...
    ribakood character(20) COLLATE pg_catalog."default",
...
);

CREATE INDEX toode_ribakood_idx
    ON firma2.toode 
    (ribakood COLLATE pg_catalog."default" ASC NULLS LAST);

查询如下trim():

explain analyze select toode,ostuhind, nimetus, pangateen
  from firma2.toode where ribakood=TRIM('TESTTOODE/H ')

不使用索引:

Gather  (cost=1000.00..575155.04 rows=4927 width=114) (actual time=101.341..2257.639 rows=1 loops=1)
  Workers Planned: 3
  Workers Launched: 0
  ->  Parallel Seq Scan on toode (cost=0.00..573662.34 rows=1589 width=114) (actual time=101.186..2257.436 rows=1 loops=1)
        Filter: ((ribakood)::text = 'TESTTOODE/H'::text)
        Rows Removed by Filter: 986481
Planning Time: 0.098 ms
Execution Time: 2257.653 ms

相同的查询,但不包含trim():

explain analyze select toode,ostuhind, nimetus, pangateen
  from firma2.toode where ribakood='TESTTOODE/H'

使用索引:

Index Scan using toode_ribakood_idx on toode  (cost=0.42..12.45 rows=2 width=114) (actual time=0.475..0.477 rows=1 loops=1)
  Index Cond: (ribakood = 'TESTTOODE/H'::bpchar)
Planning Time: 0.147 ms
Execution Time: 0.490 ms

Postgres 将ribakood列强制转换为类型text,但找不到索引。如何强制第一个查询使用trim()索引?

使用:x86_64-windows 上的 PostgreSQL 17.0,由 msvc-19.41.34120 编译,64 位

postgresql
  • 1 1 个回答
  • 44 Views

1 个回答

  • Voted
  1. Best Answer
    Richard Huxton
    2025-04-24T18:31:09+08:002025-04-24T18:31:09+08:00

    调用trim()目标值显然有点奇怪——至少ltrim()可能更合理。由于固定宽度字符类型没有ltrim()定义,它最终显然会返回文本,所以要使用索引,你只需要将结果强制转换回去即可。

    对于我在这里得到的测试表,规划器已确定它处于位图索引扫描中,但原理仍然很好。

    => EXPLAIN ANALYSE SELECT * FROM tt WHERE c = 'row 5                   ';
    ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │                                                      QUERY PLAN                                                      │
    ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │ Bitmap Heap Scan on tt  (cost=139.18..7153.38 rows=5000 width=88) (actual time=0.026..0.026 rows=1 loops=1)          │
    │   Recheck Cond: (c = 'row 5                   '::bpchar)                                                             │
    │   Heap Blocks: exact=1                                                                                               │
    │   ->  Bitmap Index Scan on tt_c_idx  (cost=0.00..137.93 rows=5000 width=0) (actual time=0.023..0.023 rows=1 loops=1) │
    │         Index Cond: (c = 'row 5                   '::bpchar)                                                         │
    │ Planning Time: 0.078 ms                                                                                              │
    │ Execution Time: 0.045 ms                                                                                             │
    └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    
    => EXPLAIN ANALYSE SELECT * FROM tt WHERE c = ltrim('row 5  ')::character(20);
    ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │                                                      QUERY PLAN                                                      │
    ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │ Bitmap Heap Scan on tt  (cost=139.18..7153.38 rows=5000 width=88) (actual time=0.040..0.041 rows=1 loops=1)          │
    │   Recheck Cond: (c = 'row 5               '::character(20))                                                          │
    │   Heap Blocks: exact=1                                                                                               │
    │   ->  Bitmap Index Scan on tt_c_idx  (cost=0.00..137.93 rows=5000 width=0) (actual time=0.031..0.031 rows=1 loops=1) │
    │         Index Cond: (c = 'row 5               '::character(20))                                                      │
    │ Planning Time: 0.129 ms                                                                                              │
    │ Execution Time: 0.051 ms                                                                                             │
    └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    

    对于那些可能遇到这种情况但并非原帖作者的人,建议永远不要使用等宽字符类型。这几乎总是错误的选择。

    • 3

相关问题

  • 如何将 jackc/pgx 与连接池、上下文、准备好的语句等一起使用

  • 编写一个 psql 查询来查找某个时间间隔内的用户

  • Postgresql 反斜杠转义字符不适用于 COPY FROM 中的逗号

  • 在基于 clojure 的 docker 容器中找不到 postgresql 库

  • 尽管违反了部分索引约束,Postgres 插入仍在发生

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve