我必须编写一个简单的查询,在其中查找以 B 或 D 开头的人名:
SELECT s.name
FROM spelers s
WHERE s.name LIKE 'B%' OR s.name LIKE 'D%'
ORDER BY 1
Run Code Online (Sandbox Code Playgroud)
我想知道是否有办法重写它以提高性能。所以我可以避免or和/或like?
postgresql index regular-expression pattern-matching string-searching
我可能在标题中问错了问题。以下是事实:
在我们基于 Django 的站点的管理界面上进行客户查询时,我的客户服务人员一直抱怨响应速度慢。
我们使用的是 Postgres 8.4.6。我开始记录慢查询,并发现了这个罪魁祸首:
SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')
Run Code Online (Sandbox Code Playgroud)
此查询的运行时间超过 32 秒。下面是 EXPLAIN 提供的查询计划:
QUERY PLAN
Aggregate (cost=205171.71..205171.72 rows=1 width=0)
-> Seq Scan on auth_user (cost=0.00..205166.46 rows=2096 width=0)
Filter: (upper((email)::text) ~~ '%DEYK%'::text)
Run Code Online (Sandbox Code Playgroud)
因为这是 Django ORM 从 Django Admin 应用程序生成的 Django QuerySet 生成的查询,所以我无法控制查询本身。索引似乎是合乎逻辑的解决方案。我尝试创建一个索引来加快速度,但没有任何区别:
CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?我怎样才能加快这个查询?
postgresql performance index pattern-matching postgresql-8.4
谁能解释一下 LIKE 运算符是如何在当前数据库系统(例如 MySQL 或 Postgres)中实现的?或者指出一些解释它的参考资料?
天真的方法是检查每条记录,在感兴趣的字段上执行正则表达式或部分字符串匹配,但我有一种感觉(希望)这些系统做一些更聪明的事情。
mysql postgresql performance full-text-search pattern-matching
今天七周内的七个数据库向我介绍了每个操作员的索引。
您可以通过创建
text_pattern_ops运算符类索引来为匹配先前查询的模式索引字符串,只要值以小写形式索引即可。
CREATE INDEX moves_title_pattern ON movies (
(lower(title) text_pattern_ops);
Run Code Online (Sandbox Code Playgroud)
我们使用 是
text_pattern_ops因为标题是文本类型。如果需要指数VARCHAR处理,字符,或名称,使用相关的OPS: ,varchar_pattern_ops,bpchar_pattern_ops和name_pattern_ops。
我觉得这个例子真的很混乱。为什么这样做有用?
如果该列是文本类型,那么在用作搜索值之前,其他类型(varchar、char、name)不会被强制转换为文本吗?
该索引的行为与使用默认运算符的索引有何不同?
CREATE INDEX moves_title_pattern ON movies (lower(title));
Run Code Online (Sandbox Code Playgroud) 在 Postgres 9.1 数据库中,我有一个table1包含约 1.5M 行和一列的表label(为了这个问题而简化了名称)。
上有一个功能性的三元组索引lower(unaccent(label))(unaccent()已被设为不可变以允许其在索引中使用)。
以下查询非常快:
SELECT count(*) FROM table1
WHERE (lower(unaccent(label)) like lower(unaccent('%someword%')));
count
-------
1
(1 row)
Time: 394,295 ms
Run Code Online (Sandbox Code Playgroud)
但以下查询速度较慢:
SELECT count(*) FROM table1
WHERE (lower(unaccent(label)) like lower(unaccent('%someword and some more%')));
count
-------
1
(1 row)
Time: 1405,749 ms
Run Code Online (Sandbox Code Playgroud)
添加更多单词甚至更慢,即使搜索更严格。
我尝试了一个简单的技巧来运行第一个单词的子查询,然后使用完整的搜索字符串进行查询,但是(可悲的是)查询计划员看穿了我的阴谋:
EXPLAIN ANALYZE
SELECT * FROM (
SELECT id, title, label from table1
WHERE lower(unaccent(label)) like lower(unaccent('%someword%'))
) t1
WHERE lower(unaccent(label)) like lower(unaccent('%someword and some more%'));
Run Code Online (Sandbox Code Playgroud)
表1上的位图堆扫描(成本=16216.01..16220.04行=1宽度=212)(实际时间=1824.017..1824.019行=1循环=1) …
postgresql full-text-search pattern-matching postgresql-9.1 postgresql-9.4
我想通过查询得到结果:
SELECT * FROM (
SELECT id, subject
FROM mailboxes
WHERE tsv @@ plainto_tsquery('avail')
) AS t1 ORDER by id DESC;
Run Code Online (Sandbox Code Playgroud)
这有效并返回tsv包含包含的行Available。但是如果我使用avai(dropped lable) 它找不到任何东西。
所有查询都必须在字典中吗?我们不能只查询这样的字母吗?我有一个包含电子邮件正文(内容)的数据库,我希望随着它每秒增长而使其快速增长。目前我正在使用
... WHERE content ~* 'letters`
Run Code Online (Sandbox Code Playgroud) 有没有办法LIKE在 ARRAY 字段上进行Postgres查询?
目前我想要这样的东西:
SELECT * FROM list WHERE lower(array_field) LIKE '1234%'
Run Code Online (Sandbox Code Playgroud)
目前不需要那么多。但是它应该在 ARRAY 中找到一个匹配的字段。这甚至可能吗?
目前我使用物化视图来生成带有 JOIN 和 a 的“列表”表ARRAY_AGG(),因为我加入了一个表,其中更多的值可能在正确的表上。这会重复左表中的字段,这不是我想要的。
编辑这就是我创建视图的方式(非常缓慢和丑陋):
CREATE MATERIALIZED VIEW article_list_new AS
SELECT a.id,
a.oa_nr,
a.date_deleted,
a.lock,
a.sds_nr,
a.kd_art_nr,
a.kd_art_index,
a.kd_art_extend,
a.surface,
a.execution,
a.surface_area,
a.cu_thickness,
a.endintensity,
a.drilling,
array_agg(o.id::text) AS offer_list
FROM article_list a LEFT JOIN task_offer o ON o.article = a.oa_nr
GROUP BY .....;
Run Code Online (Sandbox Code Playgroud)
我还需要返回task_offer表的 ID 。
我必须搜索带连字符的单词,例如“早安”、“晚安”等。
我的查询是:
select id, ts_headline(content,
to_tsquery('english','good-morning'),
'HighlightAll=true MaxFragments=100 FragmentDelimiter=$')
from table
where ts_content @@ to_tsquery('english','good-morning');
Run Code Online (Sandbox Code Playgroud)
执行此查询时,我还会分别获得“good”和“morning”的结果。但我想要完全匹配的单词和片段。
(因为ts_content我使用相同的默认配置english来创建tsvector.)
如何在 PostgreSQL 全文搜索中搜索此类带连字符的单词?
我有两张桌子。
第一个是带前缀的表
code name price
343 ek1 10
3435 nt 4
3432 ek2 2
Run Code Online (Sandbox Code Playgroud)
二是带有电话号码的通话记录
number time
834353212 10
834321242 20
834312345 30
Run Code Online (Sandbox Code Playgroud)
我需要编写一个脚本,从每条记录的前缀中找到最长的前缀,并将所有这些数据写入第三个表,如下所示:
number code ....
834353212 3435
834321242 3432
834312345 343
Run Code Online (Sandbox Code Playgroud)
对于数字 834353212,我们必须修剪 '8',然后从前缀表中找到最长的代码,即 3435。
我们必须始终先删除 '8',并且前缀必须在开头。
我很久以前以非常糟糕的方式解决了这个任务。它是糟糕的 perl 脚本,它对每条记录进行大量查询。这个脚本:
从调用表中取一个数字,在循环中从 length(number) 到 1 => $prefix 做子串
执行查询: select count(*) from prefixes where code like '$prefix'
第一个问题是查询计数 - 它是call_records * length(number). 第二个问题是LIKE表达。恐怕那些很慢。
我试图通过以下方式解决第二个问题:
CREATE EXTENSION pg_trgm;
CREATE INDEX prefix_idx ON prefix USING …Run Code Online (Sandbox Code Playgroud) postgresql performance pattern-matching postgresql-9.1 query-performance
所以我有这个包含 620 万条记录的表,我必须对列执行具有相似性的搜索查询。查询可以是:
SELECT "lca_test".* FROM "lca_test"
WHERE (similarity(job_title, 'sales executive') > 0.6)
AND worksite_city = 'los angeles'
ORDER BY salary ASC LIMIT 50 OFFSET 0
Run Code Online (Sandbox Code Playgroud)
可以在 where(year = X, worksite_state = N, status = 'certified',visa_class = Z) 中添加更多条件。
运行其中一些查询可能需要很长时间,超过 30 秒。有时超过一分钟。
EXPLAIN ANALYZE 前面提到的查询给了我这个:
Run Code Online (Sandbox Code Playgroud)Limit (cost=0.43..42523.04 rows=50 width=254) (actual time=9070.268..33487.734 rows=2 loops=1) -> Index Scan using index_lca_test_on_salary on lca_test (cost=0.43..23922368.16 rows=28129 width=254) (actual time=9070.265..33487.727 rows=2 loops=1) >>>> Filter: (((worksite_city)::text = 'los angeles'::text) AND (similarity((job_title)::text, 'sales executive'::text) > 0.6::double precision)) …
postgresql index full-text-search pattern-matching postgresql-9.3