/*$mpdf = new mPDF('', // mode - default ''
'', // format - A4, for example, default ''
0, // font size - default 0
'', // default font family
15, // margin_left
15, // margin right
16, // margin top
16, // margin bottom
9, // margin header
9, // margin footer
'L'); // L - landscape, P - portrait*/
Ваш запрос собирает много данных, поэтому можно ожидать, что он будет медленным.
Последовательное сканирование на order
является самым быстрым методом, потому что вам нужна половина строк в таблице.
В целом, PostgreSQL должен прочитать более миллиона блоков, чтобы вычислить результат и обработать все эти данные, поэтому три минуты неплохие.
Я сомневаюсь, что этот запрос можно сделать быстрее.
time
- недопустимое имя для столбца (отметка времени!), Избегайте его order
- недопустимое имя для таблицы, избегайте его now()
или +/-infinity
Также: вам, вероятно, не нужен суррогатный ключ id
на order_history
. Достаточно натурального ключа (order_id,ztime)
.
\i tmp.sql
CREATE TABLE orders (
id uuid NOT NULL
, side varchar(4) NOT NULL
, product varchar(7) NOT NULL
, price numeric(18,8) NOT NULL
, close_time timestamp NOT NULL DEFAULT ('infinity'::timestamp)
, CONSTRAINT order_pkey PRIMARY KEY (id)
);
CREATE TABLE order_history (
id serial NOT NULL
, amount numeric(18,8) NOT NULL
, ztime timestamp NOT NULL DEFAULT ('-infinity'::timestamp)
, order_id uuid NOT NULL
, CONSTRAINT order_history_pkey PRIMARY KEY (id)
, CONSTRAINT order_history_order_id_fkey FOREIGN KEY (order_id) REFERENCES orders(id)
);
-- CREATE INDEX order_history_order_id ON order_history USING btree (order_id);
-- CREATE INDEX order_history_time_idx ON order_history USING btree (ztime);
CREATE INDEX order_history_order_id_ztime ON order_history USING btree (order_id,ztime);
CREATE INDEX order_h_ztime ON orders USING btree (close_time);
EXPLAIN
select
oo.id
, oo.side
, oo.price
, oo.close_time
, oh.ztime
, oh.amount
from
orders as oo
inner join order_history as oh on oh.order_id = oo.id
where oh.ztime <= '2018-03-28 08:00:00'
and (oo.close_time > '2018-03-28 07:00:00' ) -- or oo.close_time is null)
and oo.product = 'BTC-USD'
order by oh.ztime
;
Результирующий план (без каких-либо данных !!!):
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Sort (cost=16.98..16.99 rows=1 width=92)
Sort Key: oh.ztime
-> Nested Loop (cost=3.14..16.98 rows=1 width=92)
-> Bitmap Heap Scan on orders oo (cost=1.94..13.64 rows=1 width=64)
Recheck Cond: (close_time > '2018-03-28 07:00:00'::timestamp without time zone)
Filter: ((product)::text = 'BTC-USD'::text)
-> Bitmap Index Scan on order_h_ztime (cost=0.00..1.94 rows=213 width=0)
Index Cond: (close_time > '2018-03-28 07:00:00'::timestamp without time zone)
-> Bitmap Heap Scan on order_history oh (cost=1.20..3.33 rows=2 width=44)
Recheck Cond: ((order_id = oo.id) AND (ztime <= '2018-03-28 08:00:00'::timestamp without time zone))
-> Bitmap Index Scan on order_history_order_id_ztime (cost=0.00..1.20 rows=2 width=0)
Index Cond: ((order_id = oo.id) AND (ztime <= '2018-03-28 08:00:00'::timestamp without time zone))
(12 rows)