1

我是Postgres的新手,甚至更加了解如何解釋工作原理。我有一個查詢下面這是典型的,我只需更換日期:優化兩個數百萬行表之間的內部聯接

explain 
select account_id, 
    security_id, 
    market_value_date, 
    sum(market_value) market_value 
from market_value_history mvh 
inner join holding_cust hc on hc.id = mvh.owning_object_id 
where 
hc.account_id = 24766 
and market_value_date = '2015-07-02' 
and mvh.created_by = 'HoldingLoad' 
group by account_id, security_id, market_value_date 
order by security_id, market_value_date; 

附上解釋的截圖 enter image description here 爲holding_cust表計爲2萬行和market_value_history表有1.63億行

下面是market_value_history和holding_cust的表格定義和索引:

我很感激您可能會給我調整此查詢的任何建議。

CREATE TABLE public.market_value_history 
(
    id integer NOT NULL DEFAULT nextval('market_value_id_seq'::regclass), 
    market_value numeric(18,6) NOT NULL, 
    market_value_date date, 
    holding_type character varying(25) NOT NULL, 
    owning_object_type character varying(25) NOT NULL, 
    owning_object_id integer NOT NULL, 
    created_by character varying(50) NOT NULL, 
    created_dt timestamp without time zone NOT NULL, 
    last_modified_dt timestamp without time zone NOT NULL, 
    CONSTRAINT market_value_history_pkey PRIMARY KEY (id) 
) 
WITH (
    OIDS=FALSE 
); 
ALTER TABLE public.market_value_history 
    OWNER TO postgres; 

-- Index: public.ix_market_value_history_id 

-- DROP INDEX public.ix_market_value_history_id; 

CREATE INDEX ix_market_value_history_id 
    ON public.market_value_history 
    USING btree 
    (owning_object_type COLLATE pg_catalog."default", owning_object_id); 

-- Index: public.ix_market_value_history_object_type_date 

-- DROP INDEX public.ix_market_value_history_object_type_date; 

CREATE UNIQUE INDEX ix_market_value_history_object_type_date 
    ON public.market_value_history 
    USING btree 
    (owning_object_type COLLATE pg_catalog."default", owning_object_id, holding_type COLLATE pg_catalog."default", market_value_date); 




CREATE TABLE public.holding_cust 
(
    id integer NOT NULL DEFAULT nextval('holding_cust_id_seq'::regclass), 
    account_id integer NOT NULL, 
    security_id integer NOT NULL, 
    subaccount_type integer, 
    trade_date date, 
    purchase_date date, 
    quantity numeric(18,6), 
    net_cost numeric(18,2), 
    adjusted_net_cost numeric(18,2), 
    open_date date, 
    close_date date, 
    created_by character varying(50) NOT NULL, 
    created_dt timestamp without time zone NOT NULL, 
    last_modified_dt timestamp without time zone NOT NULL, 
    CONSTRAINT holding_cust_pkey PRIMARY KEY (id) 
) 
WITH (
    OIDS=FALSE 
); 
ALTER TABLE public.holding_cust 
    OWNER TO postgres; 

-- Index: public.ix_holding_cust_account_id 

-- DROP INDEX public.ix_holding_cust_account_id; 

CREATE INDEX ix_holding_cust_account_id 
    ON public.holding_cust 
    USING btree 
    (account_id); 

-- Index: public.ix_holding_cust_acctid_secid_asofdt 

-- DROP INDEX public.ix_holding_cust_acctid_secid_asofdt; 

CREATE INDEX ix_holding_cust_acctid_secid_asofdt 
    ON public.holding_cust 
    USING btree 
    (account_id, security_id, trade_date DESC); 

-- Index: public.ix_holding_cust_security_id 

-- DROP INDEX public.ix_holding_cust_security_id; 

CREATE INDEX ix_holding_cust_security_id 
    ON public.holding_cust 
    USING btree 
    (security_id); 

-- Index: public.ix_holding_cust_trade_date 

-- DROP INDEX public.ix_holding_cust_trade_date; 

CREATE INDEX ix_holding_cust_trade_date 
    ON public.holding_cust 
    USING btree 
    (trade_date); 
+0

很高興看到'EXPLAIN ANALYZE VERBOSE',但它看起來像是對'market_value_date'和'created_by'條件進行序列掃描;爲這些索引創建** B樹**多列索引可能是合適的。 –

+0

'created_by character varying(50)NOT NULL,'看起來像一個低基數列,可以用整數FK替換爲個人表。 – joop

回答

1

兩件事情:

  1. 正如梅德指出的那樣,你應該看看上market_value_date場創建索引。它可能會發布你有一個完全不同的查詢計劃,這可能會或可能不會帶來其他瓶頸,但它肯定應該刪除這個seq-Scan
  2. 輕微(因爲我懷疑它是否會影響性能),但其次,如果您沒有按照設計實施字段長度,則可能需要將字段創建更改爲TEXT。從查詢中可以看出,它試圖將此查詢的所有創建的字段轉換爲TEXT
+0

謝謝!添加該索引完全不同 – user2395365