Оптимизация запроса с объединением, которое не использует мои индексы - PullRequest
0 голосов
/ 17 апреля 2020

Следующий запрос замедляется по мере увеличения размера моей базы данных. Я создал несколько индексов, но они не привыкли. Любые советы о том, что я могу сделать, чтобы ускорить его?

select exchange_trade.* from exchange_trade
    JOIN client_order on
        client_order.account_id = exchange_trade.account_id
            and client_order.exchange_id = exchange_trade.exchange_id
            and client_order.order_id = exchange_trade.data ->> 'order'
where client_order.algo_def_id = 1
  and client_order.account_id = 'foo'
  and exchange_trade.hedged = false
order by cast(exchange_trade.data ->> 'timestamp' AS decimal) desc

План запроса:

Sort  (cost=16122.18..16123.52 rows=536 width=839) (actual time=1637.970..1647.357 rows=1317 loops=1)
  Sort Key: (((exchange_trade.data ->> 'timestamp'::text))::numeric) DESC
  Sort Method: quicksort  Memory: 1398kB
  Buffers: shared hit=13214 read=576
  ->  Hash Join  (cost=6429.06..16097.89 rows=536 width=839) (actual time=607.431..1612.915 rows=1317 loops=1)
        Hash Cond: (((exchange_trade.exchange_id)::text = (client_order.exchange_id)::text) AND ((exchange_trade.data ->> 'order'::text) = (client_order.order_id)::text))
        Buffers: shared hit=13211 read=576
        ->  Seq Scan on exchange_trade  (cost=0.00..9099.60 rows=63983 width=807) (actual time=0.015..587.252 rows=64552 loops=1)
              Filter: ((NOT hedged) AND ((account_id)::text = 'foo'::text))
              Rows Removed by Filter: 6457
              Buffers: shared hit=8218
        ->  Hash  (cost=6321.52..6321.52 rows=7169 width=65) (actual time=607.304..607.304 rows=6928 loops=1)
              Buckets: 8192  Batches: 1  Memory Usage: 747kB
              Buffers: shared hit=4990 read=576
              ->  Seq Scan on client_order  (cost=0.00..6321.52 rows=7169 width=65) (actual time=0.120..529.715 rows=7065 loops=1)
                    Filter: (((account_id)::text = 'foo'::text) AND (algo_def_id = 1))
                    Rows Removed by Filter: 43399
                    Buffers: shared hit=4990 read=576
Planning time: 0.505 ms
Execution time: 1647.563 ms

У меня есть этот индекс:

CREATE INDEX idx_client_order_1 ON client_order (algo_def_id, account_id, exchange_id, order_id);

1 Ответ

0 голосов
/ 17 апреля 2020

Для вашего запроса вам нужны индексы:

  • client_order(algo_def_id, account_id, exchange_id)
  • exchange_trade(account_id, exchange_id)

Тем не менее, мне интересно, если запрос было бы быстрее, если бы вы использовали exists вместо join - вы выбираете только столбцы из одной таблицы.

Я был бы склонен использовать exists как:

select et.*
from exchange_trade et
where et.account_id = 'foo' and
      et.hedged = false and
      exists (select 1
              from client_order co
              where co.account_id = et.account_id and
                    co.exchange_id = et.exchange_id and
                    co.order_id = et.data ->> 'order'
                    co.algo_def_id = 1
             )
order by cast(et.data ->> 'timestamp' AS decimal) desc

Тогда для этого у вас могут быть индексы exchange_trade(account_id, hedged) и client_order(account_id, exchange_id, oder_id, algo_def_id).

Также может быть способ включить метку времени в индекс, чтобы, возможно, избежать сортировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...