SQL性能,在SELECT和WHERE条件下什么执行得更快

SQL性能,在SELECT和WHERE条件下什么执行得更快,sql,postgresql,query-optimization,query-performance,Sql,Postgresql,Query Optimization,Query Performance,更新:废话!它不是一个整数,而是字符变化(10) 像这样执行查询使用索引 SELECT t."FieldID" FROM table t WHERE t."FieldID" = '0123456789' 但如果我执行此操作,则不使用索引 SELECT t."FieldID" FROM table t WHERE t."FieldID" LIKE '01%' 还是这个 SELECT t."FieldID" FROM table t WHERE "substring"(t."FieldID",

更新:废话!它不是一个整数,而是字符变化(10)

像这样执行查询使用索引

SELECT t."FieldID"
FROM table t
WHERE t."FieldID" = '0123456789'
但如果我执行此操作,则不使用索引

SELECT t."FieldID"
FROM table t
WHERE t."FieldID" LIKE '01%'
还是这个

SELECT t."FieldID"
FROM table t
WHERE "substring"(t."FieldID", 0, 3) = '01'
还有这个

SELECT t."FieldID"
FROM table t
WHERE t."FieldID" ~ '^01'
我的索引如下所示

CREATE UNIQUE INDEX fieldid_index
  ON "table"
  USING btree
  ("FieldID");
运行PostgreSQL 7.4(Yep升级)

我正在优化我的查询,并想知道在语句的SELECT或WHERE子句中使用三种类型的表达式中的一种是否会提高性能

注意:使用这些类型的约束执行的查询将返回大约200000条记录

示例数据是一个变化的字符(10):
0123456789
,它也被索引

1。(子字符串)

2。(喜欢)

3。(RegEx)

在WHERE子句中使用一个比另一个有性能优势吗

1。(子字符串)

2。(喜欢)

3。(RegEx)


在SELECT中使用一个选项,在WHERE子句中使用另一个选项是否会提高性能

我个人认为,不应该允许制造这种问题的人使用“性能”这个词。IMHO,对数值字段(甚至可能是键字段)内容的文本表示形式的限制(如WHERE子句中的限制)表明设计不好


如果这是我的数据,我会在记录中添加一个flagfield,在查询xyz中指示想要/不想要。人们甚至可以把它放在一张单独的桌子上。我更喜欢添加一个(冗余?)列,而不是基于GW基本子字符串垃圾创建整个索引。

最有效的两件事是索引和可搜索性。Sargability意味着使用可以利用索引的表达式。您可以使用

ANALYZE your_first_table;
-- ANALYZE other tables used in this query.
EXPLAIN ANALYZE
SELECT ...
有关详细信息,请参阅文档

你可能会利用或。PostgreSQL 7.4支持表达式索引和部分索引。对于测试,您可以。(同样在7.4中。)

可能适合您的基于表达式的索引:

create index firsttwochars
on your-table-name (substring(your-column-name from 1 for 2));
但是您仍然需要测试查询,以查看它们是否实际使用了索引。(不管他们是不是sargable。)这个可能有用

select your-column-name 
from your-table-name 
where substring(your-column-name from 1 for 2) = '01'
前两个字符上没有索引的查询计划。(我的测试表使用随机纯文本用户名,这就是为什么我搜索“ab”而不是“01”。)

索引位于前两个字符上的查询计划

Bitmap Heap Scan on substring  (cost=4.36..37.61 rows=14 width=11) (actual time=0.036..0.056 rows=14 loops=1)
  Recheck Cond: (substring((username)::text, 1, 2) = 'ab'::text)
  ->  Bitmap Index Scan on firsttwochars  (cost=0.00..4.36 rows=14 width=0) (actual time=0.028..0.028 rows=14 loops=1)
        Index Cond: (substring((username)::text, 1, 2) = 'ab'::text)
Total runtime: 0.098 ms

在select列表中,这三个表达式之间可能没有太大区别。都是CPU时间

对于
WHERE
子句,可以添加表达式索引,例如

CREATE INDEX foo ON sometable ((
CASE
    WHEN "substring"("FieldID"::text, 0, 3) = '01'::text         
    THEN 1
    ELSE 0
END
));
但是这样一个布尔索引的选择性可能会很差,以至于规划者不会感兴趣。最好将
WHERE
子句重写为

WHERE "substring"("FieldID"::text, 0, 3) = '01'::text
然后索引

对于<>代码> 和ReGEX事例,您可以考虑<代码> TythOpTypnnopops索引;看


总而言之,我认为您需要对该查询进行一些清理工作。

在SQL Server中,带有
的版本(如'01%'
将是可搜索的。它实际上将这些
查询转换为类似的
查询,而不使用前导通配符来进行范围查询


执行计划将seek谓词显示为
YourCol>='01'和YourCol<'02'
也许类似的重写可以在Postgresql中有所帮助?

您不能查看执行计划,看看哪个(如果有的话)为您提供了seek而不是scan吗?使用单个查询中的任何选项只能提供scan,如何调用seek?结果集大约为200K
0123456789
不是整数,因为整数没有前导零(
123456789
是整数值)@Martin Smith:正则表达式“^01”看起来确实像字符串。整数没有前导零。这将使范围查询(Martin Smith,上图)再次成为可能。感谢您的帮助,我还更新了我的问题,以努力澄清一些问题more@PhillPafford:PostgreSQL 7.4支持部分索引和基于表达式的索引,因此,您应该能够立即提高性能。(我以为基于表达式的索引添加到了8.0中;我错了。)谢谢你的帮助,我还更新了我的问题,以便进一步澄清问题。谢谢你的帮助,我还更新了我的问题,以便进一步澄清问题。原来的问题更难看。这个话题不是关于性能的;是关于(缺乏)设计。可以理解,这不是我的设计,我只是想让一个项目按照他们指定的方式运作
ANALYZE your_first_table;
-- ANALYZE other tables used in this query.
EXPLAIN ANALYZE
SELECT ...
create index firsttwochars
on your-table-name (substring(your-column-name from 1 for 2));
select your-column-name 
from your-table-name 
where substring(your-column-name from 1 for 2) = '01'
Seq Scan on substring  (cost=0.00..205.00 rows=50 width=11) (actual time=0.315..4.377 rows=14 loops=1)
  Filter: (substring((username)::text, 1, 2) = 'ab'::text)
Total runtime: 4.414 ms
Bitmap Heap Scan on substring  (cost=4.36..37.61 rows=14 width=11) (actual time=0.036..0.056 rows=14 loops=1)
  Recheck Cond: (substring((username)::text, 1, 2) = 'ab'::text)
  ->  Bitmap Index Scan on firsttwochars  (cost=0.00..4.36 rows=14 width=0) (actual time=0.028..0.028 rows=14 loops=1)
        Index Cond: (substring((username)::text, 1, 2) = 'ab'::text)
Total runtime: 0.098 ms
CREATE INDEX foo ON sometable ((
CASE
    WHEN "substring"("FieldID"::text, 0, 3) = '01'::text         
    THEN 1
    ELSE 0
END
));
WHERE "substring"("FieldID"::text, 0, 3) = '01'::text