SQL запрос на основе исторического события и его производительности - PullRequest
0 голосов
/ 05 октября 2019

Ниже приведены таблицы и примеры данных. Я хочу получить данные до предоставленного event_id - 1 или до самого последнего, если для ngram не указан event_id, и возвращать данные только в том случае, если этот максимум (event_id) имеет некоторые данные.

Пожалуйста, посмотрите на примерыи сценарии ниже. Это проще объяснить.

CREATE TABLE NGRAM_CONTENT
(
    event_id     BIGINT PRIMARY KEY,
    ref   TEXT NOT NULL,
    data         TEXT
);

CREATE TABLE NGRAM
(
    event_id  BIGINT PRIMARY KEY,
    ngram   TEXT NOT NULL ,
    ref     TEXT not null,
    name_length INT not null,
) ;

insert into NGRAM_CONTENT(event_id, ref, data) values (1, 'p1', 'a data 1');
insert into NGRAM_CONTENT(event_id, ref, data) values (2, 'p1', 'a data 2');
insert into NGRAM_CONTENT(event_id, ref, data) values (3, 'p1', null);
insert into NGRAM_CONTENT(event_id, ref, data) values (4, 'p2', 'b data 1');
insert into NGRAM_CONTENT(event_id, ref, data) values (5, 'p2', 'b data 2');
insert into NGRAM_CONTENT(event_id, ref, data) values (6, 'p2', 'c data 1');
insert into NGRAM_CONTENT(event_id, ref, data) values (7, 'p2', 'c data 2');
insert into NGRAM(ngram, ref, event_id, name_length) values ('a', 'p1', 1, 10);
insert into NGRAM(ngram, ref, event_id, name_length) values ('a', 'p1', 2, 12);
insert into NGRAM(ngram, ref, event_id, name_length) values ('b', 'p1', 2, 13);
insert into NGRAM(ngram, ref, event_id, name_length) values ('b', 'p2', 4, 8);
insert into NGRAM(ngram, ref, event_id, name_length) values ('b', 'p2', , 10);
insert into NGRAM(ngram, ref, event_id, name_length) values ('c', 'p2', 6, 20);
insert into NGRAM(ngram, ref, event_id, name_length) values ('c', 'p2', 7, 50);

Вот таблицы с примерами ввода и желаемого результата

| ngram  | event_id | output     |
| 'a','b'| < 2      | 'a data 1' |
| 'a','b'| < 3      | 'a data 2' |
| 'a','b'| < 4      | null       |
| 'a'    | -        | null       |
| 'a'    | -        | null       |
| 'b'    | -        | null       |
| 'a','b'| -        | null       |
| 'b'    | < 5      | b data 1   |
| 'c'    | < 7      | c data 1   |
| 'c'    | -        | c data 2   |

У меня работает следующий запрос. (Я не упомянул name_length выше, поскольку это просто сложный пример). Нужно заменить 100000000 на event_id выше, а также на значения для поиска ngram

with max_matched_event_id_and_ref_from_index as
         (
             -- getting max event id and ref for all the potential matches
             select max(event_id) as max_matched_event_id, ref
             from ngram
             where name_length between 14 and 18 and
               ngram in ('a', 'b')
             and event_id < 1000000000
             group by ref
             having count(*) >= 2
         ),
     max_current_event_id as
         (
             select max(event_id) as max_current_event_id
             from ngram_content w
             inner join max_matched_event_id_and_ref_from_index n on w.ref = n.ref
             where w.event_id >= n.max_matched_event_id and event_id < 1000000000
             group by n.ref
         )
select nc.data
from ngram_content nc
         inner join max_current_event_id m on nc.event_id = m.max_current_event_id
         inner join max_matched_event_id_and_ref_from_index mi on nc.event_id = mi.max_matched_event_id;

У меня около 450 миллионов из таблицы ngram и около 55 миллионов строк из таблицы ngram_content.

текущий запрос занимает более минуты, что слишком медленно для нашего использования.

У меня есть следующие индексы:

CREATE INDEX combined_index ON NGRAM (ngram, name_length, ref, event_id);
CREATE INDEX idx_ref_ngram_content ON ngram_content (ref);
CREATE INDEX idx_ngram_content_event_id ON ngram_content (event_id);

А вот подробное объяснение выполнения плана запроса:

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Hash Join  (cost=4818702.89..4820783.06 rows=1 width=365) (actual time=29201.537..29227.214 rows=15081 loops=1)
   Hash Cond: (mi.max_matched_event_id = nc.event_id)
   Buffers: shared hit=381223 read=342422, temp read=2204 written=2213
   CTE max_matched_event_id_and_ref_from_index
     ->  Finalize GroupAggregate  (cost=3720947.79..3795574.47 rows=87586 width=16) (actual time=19163.811..19978.720 rows=43427 loops=1)
           Group Key: ngram.ref
           Filter: (count(*) >= 2)
           Rows Removed by Filter: 999474
           Buffers: shared hit=35270 read=225113, temp read=1402 written=1410
           ->  Gather Merge  (cost=3720947.79..3788348.60 rows=525518 width=24) (actual time=19163.620..19649.679 rows=1048271 loops=1)
                 Workers Planned: 2
                 Workers Launched: 2
                 Buffers: shared hit=104576 read=669841 written=1, temp read=4183 written=4207
                 ->  Partial GroupAggregate  (cost=3719947.77..3726690.76 rows=262759 width=24) (actual time=19143.782..19356.718 rows=349424 loops=3)
                       Group Key: ngram.ref
                       Buffers: shared hit=104576 read=669841 written=1, temp read=4183 written=4207
                       ->  Sort  (cost=3719947.77..3720976.62 rows=411540 width=16) (actual time=19143.770..19231.539 rows=362406 loops=3)
                             Sort Key: ngram.ref
                             Sort Method: external merge  Disk: 11216kB
                             Worker 0:  Sort Method: external merge  Disk: 11160kB
                             Worker 1:  Sort Method: external merge  Disk: 11088kB
                             Buffers: shared hit=104576 read=669841 written=1, temp read=4183 written=4207
                             ->  Parallel Index Only Scan using combined_index on ngram  (cost=0.57..3674535.28 rows=411540 width=16) (actual time=1.122..18715.404 rows=362406 loops=3)
                                   Index Cond: ((ngram = ANY ('{ORA,AN,MG}'::text[])) AND (name_length >= 14) AND (name_length <= 18) AND (event_id < 1000000000))
                                   Heap Fetches: 1087219
                                   Buffers: shared hit=104560 read=669841 written=1
   CTE max_current_event_id
     ->  GroupAggregate  (cost=1020964.39..1021403.41 rows=200 width=40) (actual time=7631.312..7674.228 rows=43427 loops=1)
           Group Key: n.ref
           Buffers: shared hit=174985 read=70887, temp read=1179 written=273
           ->  Sort  (cost=1020964.39..1021110.06 rows=58270 width=40) (actual time=7631.304..7644.203 rows=71773 loops=1)
                 Sort Key: n.ref
                 Sort Method: external merge  Disk: 2176kB
                 Buffers: shared hit=174985 read=70887, temp read=1179 written=273
                 ->  Nested Loop  (cost=0.56..1016352.18 rows=58270 width=40) (actual time=1.093..7574.448 rows=71773 loops=1)
                       Buffers: shared hit=174985 read=70887, temp read=907
                       ->  CTE Scan on max_matched_event_id_and_ref_from_index n  (cost=0.00..1751.72 rows=87586 width=40) (actual time=0.000..838.522 rows=43427 loops=1)
                             Buffers: temp read=907
                       ->  Index Scan using idx_ref_ngram_content on ngram_content w  (cost=0.56..11.57 rows=1 width=16) (actual time=0.104..0.154 rows=2 loops=43427)
                             Index Cond: (ref = n.ref)
                             Filter: ((event_id < 1000000000) AND (event_id >= n.max_matched_event_id))
                             Rows Removed by Filter: 0
                             Buffers: shared hit=174985 read=70887
   ->  CTE Scan on max_matched_event_id_and_ref_from_index mi  (cost=0.00..1751.72 rows=87586 width=8) (actual time=19163.813..19168.081 rows=43427 loops=1)
         Buffers: shared hit=35270 read=225113, temp read=495 written=1410
   ->  Hash  (cost=1722.50..1722.50 rows=200 width=381) (actual time=10035.797..10035.797 rows=43427 loops=1)
         Buckets: 32768 (originally 1024)  Batches: 2 (originally 1)  Memory Usage: 3915kB
         Buffers: shared hit=345953 read=117309, temp read=1179 written=704
         ->  Nested Loop  (cost=0.56..1722.50 rows=200 width=381) (actual time=7632.365..9994.328 rows=43427 loops=1)
               Buffers: shared hit=345953 read=117309, temp read=1179 written=273
               ->  CTE Scan on max_current_event_id m  (cost=0.00..4.00 rows=200 width=8) (actual time=7631.315..7695.869 rows=43427 loops=1)
                     Buffers: shared hit=174985 read=70887, temp read=1179 written=273
               ->  Index Scan using idx_ngram_content_event_id on ngram_content nc  (cost=0.56..8.58 rows=1 width=373) (actual time=0.052..0.052 rows=1 loops=43427)
                     Index Cond: (event_id = m.max_current_event_id)
                     Buffers: shared hit=170968 read=46422
 Planning Time: 7.872 ms
 Execution Time: 29231.222 ms
(57 rows)

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

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