Индекс существует, но сортировка все еще занимает время - PullRequest
0 голосов
/ 01 июля 2019

Я работаю над запросом, который использовался в одном из наших сервисов. Ниже приведен запрос:

select rg.reservationGuestId, rg.reservationId, rg.checkindate, rg.checkoutdate, rg.assignedroom , tr.orderDate, tr.assignedDate, 
cast(tr.orderId as char(36)) , g.titleCode, g.firstName, g.middleName, g.lastName, g.birthDate, g.genderCode, g.email, g.preferredLanguage , 
cast(a.addressId as char(36)), a.addressTypeCode, a.line1, a.line2, a.city, a.state, a.countryCode as aCountryCode, a.zip , cast(p.phoneId as char(36)), 
p.phoneTypeCode, p.countryCode as pCountryCode, p.areaCode, p.number 
 from reservationguest rg  
inner join guest g on rg.guestid = g.guestid 
 inner join address a on g.guestid = a.guestid 
  inner join phone p on g.guestid = p.guestid 
   left join orderdetail tr on rg.reservationguestid = tr.reservationguestid 
where ((0 = 0) or (rg.reservationGuestId in (null)))
 and (('2019-05-01' = 'null') or (rg.checkindate >= '2019-05-01')) and (('2019-09-08' = 'null') or (rg.checkindate <= '2019-09-08')) 
  and ((1 = 0) or (a.addressTypeCode in ('SHIPPING'))) and ((1 = 0) or (p.phoneTypeCode in ('HOME'))) 
   and (('' = 'null') or (('' = '') and (tr.orderDate is null)) or (tr.orderDate = '2019-06-02 00:00:00')) 
order by rg.checkindate, rg.lastmodifieddate

Вышеупомянутый запрос занимает почти 1150 мс при извлечении 161500 записей.

Ниже приведен план выполнения этого запроса:

Sort  (cost=21727.93..21732.95 rows=2009 width=683) (actual time=928.206..1117.145 rows=161500 loops=1)
  Sort Key: rg.checkindate, rg.lastmodifieddate
  Sort Method: external merge  Disk: 55936kB
  ->  Hash Right Join  (cost=15262.53..21617.71 rows=2009 width=683) (actual time=267.553..576.902 rows=161500 loops=1)
        Hash Cond: ((tr.reservationguestid)::text = (rg.reservationguestid)::text)
        Filter: ((tr.orderdate IS NULL) OR (tr.orderdate = '2019-06-02 00:00:00'::timestamp without time zone))
        Rows Removed by Filter: 252112
        ->  Seq Scan on orderdetail tr  (cost=0.00..6047.00 rows=66800 width=69) (actual time=0.018..36.367 rows=66887 loops=1)
        ->  Hash  (cost=15210.52..15210.52 rows=4161 width=255) (actual time=266.789..266.789 rows=18521 loops=1)
              Buckets: 16384 (originally 8192)  Batches: 2 (originally 1)  Memory Usage: 3969kB
              ->  Nested Loop  (cost=5302.72..15210.52 rows=4161 width=255) (actual time=62.445..248.868 rows=18521 loops=1)
                    ->  Hash Join  (cost=5302.30..6748.12 rows=3322 width=258) (actual time=62.378..83.816 rows=6762 loops=1)
                          Hash Cond: ((p.guestid)::text = (g.guestid)::text)
                          ->  Bitmap Heap Scan on phone p  (cost=263.88..1624.42 rows=13883 width=70) (actual time=1.482..13.057 rows=13909 loops=1)
                                Recheck Cond: ((phonetypecode)::text = 'HOME'::text)
                                Heap Blocks: exact=1186
                                ->  Bitmap Index Scan on ix_phone_phonetypecode  (cost=0.00..260.41 rows=13883 width=0) (actual time=1.315..1.315 rows=13909 loops=1)
                                      Index Cond: ((phonetypecode)::text = 'HOME'::text)
                          ->  Hash  (cost=4952.89..4952.89 rows=6842 width=188) (actual time=60.860..60.860 rows=6811 loops=1)
                                Buckets: 8192  Batches: 1  Memory Usage: 1664kB
                                ->  Hash Join  (cost=1774.72..4952.89 rows=6842 width=188) (actual time=28.954..56.879 rows=6811 loops=1)
                                      Hash Cond: ((a.guestid)::text = (g.guestid)::text)
                                      ->  Bitmap Heap Scan on address a  (cost=137.45..3221.97 rows=6842 width=100) (actual time=1.174..22.254 rows=6811 loops=1)
                                            Recheck Cond: ((addresstypecode)::text = 'SHIPPING'::text)
                                            Heap Blocks: exact=2290
                                            ->  Bitmap Index Scan on ix_address_addresstypecode  (cost=0.00..135.73 rows=6842 width=0) (actual time=0.877..0.877 rows=6811 loops=1)
                                                  Index Cond: ((addresstypecode)::text = 'SHIPPING'::text)
                                      ->  Hash  (cost=1279.90..1279.90 rows=28590 width=88) (actual time=27.704..27.704 rows=28590 loops=1)
                                            Buckets: 32768  Batches: 1  Memory Usage: 3708kB
                                            ->  Seq Scan on guest g  (cost=0.00..1279.90 rows=28590 width=88) (actual time=0.015..17.576 rows=28590 loops=1)
                    ->  Index Scan using ix_reservationguest_guestid_checkindate_lastmodifieddate on reservationguest rg  (cost=0.42..2.53 rows=2 width=129) (actual time=0.015..0.023 rows=3 loops=6762)
                          Index Cond: (((guestid)::text = (g.guestid)::text) AND (checkindate >= '2019-05-01'::date) AND (checkindate <= '2019-09-08'::date))
Planning time: 3.343 ms
Execution time: 1173.074 ms 

Я думаю, что запрос в значительной степени оптимизирован. Однако после удаления предложения order by это занимает около 550 мс, что составляет почти половину общего времени.

Поскольку я очень мало знаю о внутренностях PostgreSQL, я не уверен насчет сортировки с использованием индекса ix_reservationguest_guestid_checkindate_lastmodifieddate, поскольку в плане выполнения не упоминается имя индекса с операцией сортировки.

Вопросы

  • Если он использует индекс для сортировки, то это минимальное время выполнения, которое я могу получить от Postgres?

  • Если он не использует индекс, то есть ли способ повысить производительность сортировки?

  • Кроме того, какой индекс следует создать, чтобы избежать сканирования Seq таблицы orderdetail?

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