PostgreSQL表索引
我想为以下查询的表编制索引:PostgreSQL表索引,postgresql,performance,indexing,Postgresql,Performance,Indexing,我想为以下查询的表编制索引: select t.* from main_transaction t left join main_profile profile on profile.id = t.profile_id left join main_customer customer on (customer.id = profile.user_id) where (upper(t.request_no) like upper(('%'||@requestNumber||'%'))
select
t.*
from main_transaction t
left join main_profile profile on profile.id = t.profile_id
left join main_customer customer on (customer.id = profile.user_id)
where
(upper(t.request_no) like upper(('%'||@requestNumber||'%')) or OR upper(c.phone) LIKE upper(concat('%',||@phoneNumber||,'%')))
and t.service_type = 'SERVICE_1'
and t.status = 'SUCCESS'
and t.mode = 'AUTO'
and t.transaction_type = 'WITHDRAW'
and customer.client = 'corp'
and t.pub_date>='2018-09-05' and t.pub_date<='2018-11-05'
order by t.pub_date desc, t.id asc
LIMIT 1000;
在像上面那样建立索引之后,我的查询花费了4.5秒来选择1000行
我从下表中进行选择,该表有34列,包括3个外键,数据行数超过300万行:
CREATE TABLE main_transaction (
id integer NOT NULL DEFAULT nextval('main_transaction_id_seq'::regclass),
description character varying(255) NOT NULL,
request_no character varying(18),
account character varying(50),
service_type character varying(50),
pub_date" timestamptz(6) NOT NULL,
"service_id" varchar(50) COLLATE "pg_catalog"."default",
....
);
我还加入了两个表(main\u profile
,main\u customer
),用于搜索customer.phone
和选择customer.client
。要从main\u交易
表访问main\u客户
表,我只能通过main\u配置文件
我的问题是如何为表编制索引以提高上述查询的性能
请不要对使用UNION
或对这种情况使用(上限(t.request_no)像上限(“%”| |@requestNumber | |‘%”)或上限(c.phone)像上限(concat(“%”,| | | phoneNumber | |,“%”))
当出现情况时,我们可以使用大小写吗?因为,我必须将我的PostgreSQL查询转换为HibernateJPA!我不知道如何转换UNION
,除了Hibernate-Native-SQL
之外,我不允许使用它
说明:
Limit (cost=411601.73..411601.82 rows=38 width=1906) (actual time=3885.380..3885.381 rows=1 loops=1)
-> Sort (cost=411601.73..411601.82 rows=38 width=1906) (actual time=3885.380..3885.380 rows=1 loops=1)
Sort Key: t.pub_date DESC, t.id
Sort Method: quicksort Memory: 27kB
-> Hash Join (cost=20817.10..411600.73 rows=38 width=1906) (actual time=3214.473..3885.369 rows=1 loops=1)
Hash Cond: (t.profile_id = profile.id)
Join Filter: ((upper((t.request_no)::text) ~~ '%20181104-2158-2723948%'::text) OR (upper((customer.phone)::text) ~~ '%20181104-2158-2723948%'::text))
Rows Removed by Join Filter: 593118
-> Seq Scan on main_transaction t (cost=0.00..288212.28 rows=205572 width=1906) (actual time=0.068..1527.677 rows=593119 loops=1)
Filter: ((pub_date >= '2016-09-05 00:00:00+05'::timestamp with time zone) AND (pub_date <= '2018-11-05 00:00:00+05'::timestamp with time zone) AND ((service_type)::text = 'SERVICE_1'::text) AND ((status)::text = 'SUCCESS'::text) AND ((mode)::text = 'AUTO'::text) AND ((transaction_type)::text = 'WITHDRAW'::text))
Rows Removed by Filter: 2132732
-> Hash (cost=17670.80..17670.80 rows=180984 width=16) (actual time=211.211..211.211 rows=181516 loops=1)
Buckets: 131072 Batches: 4 Memory Usage: 3166kB
-> Hash Join (cost=6936.09..17670.80 rows=180984 width=16) (actual time=46.846..183.689 rows=181516 loops=1)
Hash Cond: (customer.id = profile.user_id)
-> Seq Scan on main_customer customer (cost=0.00..5699.73 rows=181106 width=16) (actual time=0.013..40.866 rows=181618 loops=1)
Filter: ((client)::text = 'corp'::text)
Rows Removed by Filter: 16920
-> Hash (cost=3680.04..3680.04 rows=198404 width=8) (actual time=46.087..46.087 rows=198404 loops=1)
Buckets: 131072 Batches: 4 Memory Usage: 2966kB
-> Seq Scan on main_profile profile (cost=0.00..3680.04 rows=198404 width=8) (actual time=0.008..20.099 rows=198404 loops=1)
Planning time: 0.757 ms
Execution time: 3885.680 ms
限制(成本=411601.73..411601.82行=38宽=1906)(实际时间=3885.380..3885.381行=1圈=1)
->排序(成本=411601.73..411601.82行=38宽度=1906)(实际时间=3885.380..3885.380行=1循环=1)
排序键:t.pub_date DESC,t.id
排序方法:快速排序内存:27kB
->散列联接(成本=20817.10..411600.73行=38宽度=1906)(实际时间=3214.473..3885.369行=1循环=1)
散列条件:(t.profile\u id=profile.id)
加入筛选器:((上限((t.request_no)::text)~'%20181104-2158-2723948%::text)或(上限((customer.phone)::text)~'%20181104-2158-2723948%::text))
被联接筛选器删除的行:593118
->主事务t上的顺序扫描(成本=0.00..288212.28行=205572宽度=1906)(实际时间=0.068..1527.677行=593119循环=1)
筛选器:((发布日期>='2016-09-05 00:00:00+05'::带时区的时间戳)和(发布日期哈希(成本=17670.80..17670.80行=180984宽度=16)(实际时间=211.211..211.211行=181516循环=1)
存储桶:131072批:4内存使用率:3166kB
->散列联接(成本=6936.09..17670.80行=180984宽度=16)(实际时间=46.846..183.689行=181516循环=1)
散列条件:(customer.id=profile.user\u id)
->主要客户的顺序扫描(成本=0.00..5699.73行=181106宽度=16)(实际时间=0.013..40.866行=181618循环=1)
筛选器:((客户端)::text='corp'::text)
被筛选器删除的行:16920
->散列(成本=3680.04..3680.04行=198404宽度=8)(实际时间=46.087..46.087行=198404循环=1)
存储桶:131072批:4内存使用率:2966kB
->主_剖面上的顺序扫描(成本=0.00..3680.04行=198404宽度=8)(实际时间=0.008..20.099行=198404循环=1)
计划时间:0.757毫秒
执行时间:3885.680毫秒
有不使用工会的限制,你不会得到一个好的计划
您可以使用以下索引稍微加快处理速度:
main_transaction ((service_type::text), (status::text), (mode::text),
(transaction_type::text), pub_date)
main_customer ((client::text))
这些应该至少可以消除顺序扫描,但占用大部分处理时间的哈希连接将保留。因为您使用的是*
,而postgresql选择seq scan
,只需选择您需要的列。然后再次查看计划执行postgresql所做的事情。@LaurenzAlbe。您能给出建议吗?
main_transaction ((service_type::text), (status::text), (mode::text),
(transaction_type::text), pub_date)
main_customer ((client::text))