请原谅实际查询的简化。只是为了让它可读。目前,在按主键添加订单时,我们的查询速度会降低。
select id, field1, field2
from table1
where field1 = 'value'
limit 1000;
因此拥有field1的索引,此查询使用该索引,这使得查询更快。我可以通过explain命令跟踪查询规划器使用该索引。
通过突然更改用于主键索引的索引来添加订单。这使查询慢了很多。
select id, field1, field2
from table1 where field1 = 'value'
order by id asc
limit 1000;
有没有办法强制查询规划器使用field1索引?
编辑: 实际表格详细信息:
\d fax_message
Table "public.fax_message"
Column | Type | Modifiers
--------------------------+-----------------------------+-----------
id | bigint | not null
broadcast_ref | character varying(255) |
busy_retries | integer |
cli | character varying(255) |
dncr | boolean | not null
document_set_id | bigint | not null
fax_broadcast_attempt_id | bigint |
fps | boolean | not null
header_format | character varying(255) |
last_updated | timestamp without time zone | not null
max_fax_pages | integer |
message_ref | character varying(255) |
must_be_sent_before_date | timestamp without time zone |
request_id | bigint |
resolution | character varying(255) |
retries | integer |
send_from | character varying(255) |
send_ref | character varying(255) |
send_to | character varying(255) | not null
smartblock | boolean | not null
status | character varying(255) | not null
time_zone | character varying(255) |
total_pages | integer |
user_id | uuid | not null
delay_status_check_until | timestamp without time zone |
version | bigint | default 0
cost | numeric(40,10) | default 0
Indexes:
"fax_message_pkey" PRIMARY KEY, btree (id)
"fax_message_broadcast_ref_idx" btree (broadcast_ref)
"fax_message_delay_status_check_until" btree (delay_status_check_until)
"fax_message_document_set_idx" btree (document_set_id)
"fax_message_fax_broadcast_attempt_idx" btree (fax_broadcast_attempt_id)
"fax_message_fax_document_set_idx" btree (document_set_id)
"fax_message_message_ref_idx" btree (message_ref)
"fax_message_request_idx" btree (request_id)
"fax_message_send_ref_idx" btree (send_ref)
"fax_message_status_fax_broadcast_attempt_idx" btree (status, fax_broadcast_attempt_id)
"fax_message_user" btree (user_id)
Foreign-key constraints:
"fk2881c4e5106ed2de" FOREIGN KEY (request_id) REFERENCES core_api_send_fax_request(id)
"fk2881c4e5246f3088" FOREIGN KEY (document_set_id) REFERENCES fax_document_set(id)
"fk2881c4e555aad98b" FOREIGN KEY (user_id) REFERENCES users(id)
"fk2881c4e59920b254" FOREIGN KEY (fax_broadcast_attempt_id) REFERENCES fax_broadcast_attempt(id)
Referenced by:
TABLE "fax_message_status_modifier" CONSTRAINT "fk2dfbe52acb955ec1" FOREIGN KEY (fax_message_id) REFERENCES fax_message(id)
TABLE "fax_message_attempt" CONSTRAINT "fk82058973cb955ec1" FOREIGN KEY (fax_message_id) REFERENCES fax_message(id)
使用的实际指数:
\d fax_message_status_fax_broadcast_attempt_idx
Index "public.fax_message_status_fax_broadcast_attempt_idx"
Column | Type | Definition
--------------------------+------------------------+--------------------------
status | character varying(255) | status
fax_broadcast_attempt_id | bigint | fax_broadcast_attempt_id
btree, for table "public.fax_message"
真实查询:
订购方式:
explain select this_.id as id65_0_, this_.version as version65_0_, this_.broadcast_ref as broadcast3_65_0_, this_.busy_retries as busy4_65_0_, this_.cli as cli65_0_, this_.cost as cost65_0_, this_.delay_status_check_until as delay7_5_0_, this_.dncr as dncr65_0_, this_.document_set_id as document9_65_0_, this_.fax_broadcast_attempt_id as fax10_65_0_, this_.fps as fps65_0_, this_.header_format as header12_65_0_, this_.last_updated as last13_65_0_, this_.max_fax_pages as max14_65_0_, this_.message_ref as message15_65_0_, this_.must_be_sent_before_date as must16_65_0_, this_.request_id as request17_65_0_, this_.resolution as resolution65_0_, this_.retries as retries65_0_, this_.send_from as send20_65_0_, this_.send_ref as send21_65_0_, this_.send_to as send22_65_0_, this_.smartblock as smartblock65_0_, this_.status as status65_0_, this_.time_zone as time25_65_0_, this_.total_pages as total26_65_0_, this_.user_id as user27_65_0_ from fax_message this_ where this_.status='TO_CHARGE_GROUP' order by id asc limit 1000;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Limit (cost=0.43..53956.06 rows=1000 width=2234)
-> Index Scan using fax_message_pkey on fax_message this_ (cost=0.43..2601902.61 rows=48223 width=2234)
Filter: ((status)::text = 'TO_CHARGE_GROUP'::text)
(3 rows)
这个没有订单的那个:
explain select this_.id as id65_0_, this_.version as version65_0_, this_.broadcast_ref as broadcast3_65_0_, this_.busy_retries as busy4_65_0_, this_.cli as cli65_0_, this_.cost as cost65_0_, this_.delay_status_check_until as delay7_5_0_, this_.dncr as dncr65_0_, this_.document_set_id as document9_65_0_, this_.fax_broadcast_attempt_id as fax10_65_0_, this_.fps as fps65_0_, this_.header_format as header12_65_0_, this_.last_updated as last13_65_0_, this_.max_fax_pages as max14_65_0_, this_.message_ref as message15_65_0_, this_.must_be_sent_before_date as must16_65_0_, this_.request_id as request17_65_0_, this_.resolution as resolution65_0_, this_.retries as retries65_0_, this_.send_from as send20_65_0_, this_.send_ref as send21_65_0_, this_.send_to as send22_65_0_, this_.smartblock as smartblock65_0_, this_.status as status65_0_, this_.time_zone as time25_65_0_, this_.total_pages as total26_65_0_, this_.user_id as user27_65_0_ from fax_message this_ where this_.status='TO_CHARGE_GROUP' limit 1000;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.56..1744.13 rows=1000 width=2234)
-> Index Scan using fax_message_status_fax_broadcast_attempt_idx on fax_message this_ (cost=0.56..84080.59 rows=48223 width=2234)
Index Cond: ((status)::text = 'TO_CHARGE_GROUP'::text)
(3 rows)
使用fax_message_pkey的查询的开销大于使用fax_message_status_fax_broadcast_attempt_idx的查询的最大开销。 我希望查询仍然会使用fax_message_status_fax_broadcast_attempt_idx索引,即使是那里的订单。
答案 0 :(得分:0)
根据How do I force Postgres to use a particular index?(以及答案中的链接),似乎没有办法强制使用特定索引。
答案 1 :(得分:0)
CTE是一个优化范围。您没有向我们提供足够的信息来告诉您为什么您的查询计划错误,但如果您不关心实际解决问题,这应该有用。
WITH t AS (
select id, field1, field2
from table1
where field1 = 'value'
limit 1000
)
SELECT *
FROM t
order by id asc;