Answers:
您的查询几乎是最佳的。语法不会变短,查询不会变快:
SELECT name
FROM   spelers
WHERE  name LIKE 'B%' OR name LIKE 'D%'
ORDER  BY 1;如果您确实想缩短语法,请使用带有分支的正则表达式:
...
WHERE  name ~ '^(B|D).*'或稍快一点,使用一个字符类:
...
WHERE  name ~ '^[BD].*'SIMILAR TO对我而言,没有索引的快速测试所产生的结果比任何一种情况下都更快。
有了适当的B树索引,就可以在LIKE这场比赛中胜出几个数量级。
如果您担心性能,请为更大的表创建这样的索引:
CREATE INDEX spelers_name_special_idx ON spelers (name text_pattern_ops);使这种查询的速度提高几个数量级。特殊注意事项适用于特定于语言环境的排序顺序。在手册中阅读有关操作符类的更多信息。如果您使用标准的“ C”语言环境(大多数人不使用),则将使用纯索引(具有默认的运算符类)。
这样的索引仅适用于左锚模式(从字符串开头开始匹配)。
SIMILAR TO或带有基本左锚表达式的正则表达式也可以使用此索引。但不包含分支(B|D)或字符类[BD](至少在我对PostgreSQL 9.0的测试中)。
Trigram匹配或文本搜索使用特殊的GIN或GiST索引。
LIKE(~~)简单,快速,但功能有限。
ILIKE(~~*)不区分大小写的变体。
pg_trgm扩展了两者的索引支持。
~ (正则表达式匹配)功能强大但更复杂,除基本表达式外,其他任何东西的运行速度都可能很慢。
SIMILAR TO仅仅是毫无意义的。LIKE正则表达式的特殊混血。我从不使用它。见下文。
%是附加模块提供的“相似”运算符pg_trgm。见下文。
@@是文本搜索运算符。见下文。
从PostgreSQL 9.1开始,您可以方便扩展使用GIN或GiST索引pg_trgm为任何 LIKE / ILIKE模式(以及带有的简单正则表达式模式~)提供索引支持。
详细信息,示例和链接:
pg_trgm还提供以下运算符:
% -“相似性”运算符 <%(换向器:%>)-Postgres 9.6或更高版本中的“ word_similarity”运算符<<%(换向器:%>>)-Postgres 11或更高版本中的“ strict_word_similarity”运算符是与单独的基础结构和索引类型匹配的一种特殊类型的模式。它使用字典和词干,是在文档中查找单词的好工具,特别是对于自然语言。
还支持前缀匹配:
从Postgres 9.6开始,还有短语搜索:
请考虑手册中的介绍以及操作员和功能的概述。
附加模块Fuzzystrmatch提供了更多选项,但是性能通常不如上述所有。
特别地,levenshtein()功能的各种实现可以是有用的。
~)总是比快SIMILAR TO?答案很简单。SIMILAR TO表达式在内部被重写为正则表达式。因此,对于每个SIMILAR TO表达式,至少有一个更快的正则表达式(这节省了重写表达式的开销)。使用SIMILAR TO ever不会提高性能。
无论如何,可以使用LIKE(~~)完成的简单表达式都更快LIKE。
SIMILAR TO仅在PostgreSQL中受支持,因为它最终出现在SQL标准的早期草案中。他们仍然没有摆脱它。但是有计划将其删除,而改为包含正则表达式匹配项-或我听说。
EXPLAIN ANALYZE揭示它。自己尝试使用任何桌子!
EXPLAIN ANALYZE SELECT * FROM spelers WHERE name SIMILAR TO 'B%';揭示了:
...  
Seq Scan on spelers  (cost= ...  
  Filter: (name ~ '^(?:B.*)$'::text)SIMILAR TO已使用正则表达式(~)重写。
但EXPLAIN ANALYZE揭示更多。尝试使用上述索引:
EXPLAIN ANALYZE SELECT * FROM spelers WHERE name ~ '^B.*;揭示了:
...
 ->  Bitmap Heap Scan on spelers  (cost= ...
       Filter: (name ~ '^B.*'::text)
        ->  Bitmap Index Scan on spelers_name_text_pattern_ops_idx (cost= ...
              Index Cond: ((prod ~>=~ 'B'::text) AND (prod ~<~ 'C'::text))在内部,与未识别语言代码的索引(text_pattern_ops或使用区域C)简单的左锚定表达式用这些文字图案运营商改写为:~>=~,~<=~,~>~,~<~。这是的情况下~,~~或SIMILAR TO相似。
varchar具有varchar_pattern_ops或char具有的类型上的索引也是如此bpchar_pattern_ops。
因此,将其应用于原始问题,这是最快的方法:
SELECT name
FROM   spelers  
WHERE  name ~>=~ 'B' AND name ~<~ 'C'
    OR name ~>=~ 'D' AND name ~<~ 'E'
ORDER  BY 1;当然,如果您碰巧要搜索相邻的缩写,则可以进一步简化:
WHERE  name ~>=~ 'B' AND name ~<~ 'D'   -- strings starting with B or C与~或的普通使用相比,收益~~很小。如果性能不是您的首要要求,那么您应该坚持使用标准操作员-得出问题中已有的内容。
similar一次扫描吗?
                    EXPLAIN ANALYZE显示2个位图索引扫描。多个位图索引扫描可以相当快速地组合在一起。
                    OR用UNION ALL或更换name LIKE 'B%'与   name >= 'B' AND name <'C'Postgres里?
                    UNION不会,但是,是的,将范围合并为一个WHERE子句将加快查询速度。我在答案中添加了更多内容。当然,您必须考虑到您的语言环境。区域设置感知搜索总是较慢。
                    如何在表中添加一列。根据您的实际要求:
person_name_start_with_B_or_D (Boolean)
person_name_start_with_char CHAR(1)
person_name_start_with VARCHAR(30)PostgreSQL 在SQL Server中不支持基表中的计算列,但可以通过触发器维护新列。显然,该新列将被索引。
CREATE INDEX spelers_name_initial_idx ON spelers (left(name, 1)); 在其条件下与表达式匹配的查询可以利用此索引。
这样,在创建或修改数据时会导致性能下降,因此可能仅适用于低活动性环境(即写入次数少于读取次数)。
你可以试试
SELECT s.name
FROM   spelers s
WHERE  s.name SIMILAR TO '(B|D)%' 
ORDER  BY s.name我不知道上面或您的原始表达式是否在Postgres中都是可修饰的。
如果您创建建议的索引,也将有兴趣了解它与其他选项的比较。
SELECT name
FROM   spelers
WHERE  name >= 'B' AND name < 'C'
UNION ALL
SELECT name
FROM   spelers
WHERE  name >= 'D' AND name < 'E'
ORDER  BY name很老的问题,但是我找到了解决这个问题的另一种快速解决方案:
SELECT s.name 
FROM spelers s 
WHERE ascii(s.name) in (ascii('B'),ascii('D'))
ORDER BY 1由于函数ascii()仅查看字符串的第一个字符。
(name)吗?
                    为了检查首字母缩写,我经常使用强制转换为"char"(带有双引号)。它不是便携式的,但速度很快。在内部,它简单地删除文本并返回第一个字符,并且“ char”比较操作非常快,因为类型为1字节固定长度:
SELECT s.name 
FROM spelers s 
WHERE s.name::"char" =ANY( ARRAY[ "char" 'B', 'D' ] )
ORDER BY 1请注意,强制转换为to "char"的速度比ascii()@ Sole021的速度快,但它与UTF8不兼容(或与此相关的任何其他编码),仅返回第一个字节,因此仅应在与普通旧7比较的情况下使用位ASCII字符。
进行单个字符比较可能更快:
SUBSTR(s.name,1,1)='B' OR SUBSTR(s.name,1,1)='D'column LIKE 'B%'比在该列上使用子字符串函数更有效。
                    
s.name索引了吗?