| | 421 | |
| | 422 | |
| | 423 | |
| | 424 | |
| | 425 | |
| | 426 | |
| | 427 | |
| | 428 | == Анализа и оптимизација на `Future_Events` |
| | 429 | |
| | 430 | Овој поглед служи за динамично генерирање на репертоарот, прикажувајќи ги исклучиво претстојните настани преку филтрирање на изминатите термини во однос на моменталното време на системот. Дополнително, тој ја прикажува комплетната географска адреса и локација на објектот каде ќе се одржи настанот. |
| | 431 | |
| | 432 | {{{ |
| | 433 | |
| | 434 | CREATE OR REPLACE VIEW "Future_Events" AS |
| | 435 | SELECT |
| | 436 | e.event_id, |
| | 437 | e.name AS event_name, |
| | 438 | eh.event_happening_id, |
| | 439 | eh.event_time, |
| | 440 | v.venue_id, |
| | 441 | v.name AS venue_name, |
| | 442 | v.address_street AS street, |
| | 443 | v.address_city AS city, |
| | 444 | v.address_country AS country |
| | 445 | FROM "Event" e |
| | 446 | JOIN "Event_Happening" eh ON e.event_id = eh.event_id |
| | 447 | JOIN "Venue" v ON eh.venue_id = v.venue_id |
| | 448 | WHERE eh.event_time > CURRENT_TIMESTAMP; |
| | 449 | |
| | 450 | }}} |
| | 451 | |
| | 452 | ==== 1. Примарен филтер: |
| | 453 | |
| | 454 | Примарниот филтер е колоната `event_time` во табелата `Event_Happening`. Погледот постојано го бара само подмножеството на записи кои се во иднина. |
| | 455 | |
| | 456 | ==== 2. Случај на употреба: |
| | 457 | |
| | 458 | Овој поглед е „лицето“ на платформата. Се користи при вчитување на листата на претстојни настани за корисниците. Ефикасноста овде директно го дефинира времето на првично вчитување на апликацијата. |
| | 459 | |
| | 460 | ==== 3. Иницијално време: |
| | 461 | |
| | 462 | * '''SELECT:''' 100.080 ms (Бавно поради '''Seq Scan''' низ илјадници записи во `Event_Happening` за проверка на времето). |
| | 463 | * '''INSERT:''' 12.452 ms (Процесирањето на тригерите и запишувањето на податокот). |
| | 464 | * '''UPDATE:''' 0.104 ms (Инстантна брзина преку '''primary key'''). |
| | 465 | |
| | 466 | ==== 4. Анализа на планот на извршување (без индекси): |
| | 467 | |
| | 468 | Без индекс на времето, базата мораше да прави '''Sequential Scan''' низ целата табела `Event_Happening` (12,973 записи), што резултираше со бавно филтрирање во меморијата ('''Filter: `event_time > CURRENT_TIMESTAMP`'''). Дополнително, базата трошеше непотребни 466 читања од диск за да ја провери секоја редица. |
| | 469 | |
| | 470 | * '''SELECT''' |
| | 471 | |
| | 472 | {{{ |
| | 473 | |
| | 474 | EXPLAIN ANALYZE |
| | 475 | SELECT * FROM "Future_Events" |
| | 476 | WHERE city = 'London'; |
| | 477 | |
| | 478 | }}} |
| | 479 | |
| | 480 | ||= QUERY PLAN =|| |
| | 481 | ||Nested Loop (cost\=263.49..1377.68 rows\=332 width\=121) (actual time\=3.243..100.080 rows\=340.00 loops\=1)|| |
| | 482 | || Buffers: shared hit\=778 read\=844|| |
| | 483 | || -> Hash Join (cost\=263.20..1234.31 rows\=332 width\=90) (actual time\=2.695..18.025 rows\=340.00 loops\=1)|| |
| | 484 | || Hash Cond: (eh.venue_id \= v.venue_id)|| |
| | 485 | || Buffers: shared hit\=2 read\=600|| |
| | 486 | || -> Seq Scan on ""Event_Happening"" eh (cost\=0.00..937.09 rows\=12957 width\=32) (actual time\=0.154..12.105 rows\=12973.00 loops\=1)|| |
| | 487 | || Filter: (event_time > CURRENT_TIMESTAMP)|| |
| | 488 | || Rows Removed by Filter: 18365|| |
| | 489 | || Buffers: shared hit\=1 read\=466|| |
| | 490 | || -> Hash (cost\=260.00..260.00 rows\=256 width\=66) (actual time\=2.516..2.517 rows\=256.00 loops\=1)|| |
| | 491 | || Buckets: 1024 Batches: 1 Memory Usage: 33kB|| |
| | 492 | || Buffers: shared hit\=1 read\=134|| |
| | 493 | || -> Seq Scan on ""Venue"" v (cost\=0.00..260.00 rows\=256 width\=66) (actual time\=0.222..2.393 rows\=256.00 loops\=1)|| |
| | 494 | || Filter: ((address_city)::text \= 'London'::text)|| |
| | 495 | || Rows Removed by Filter: 9744|| |
| | 496 | || Buffers: shared hit\=1 read\=134|| |
| | 497 | || -> Index Scan using ""Event_pkey"" on ""Event"" e (cost\=0.29..0.43 rows\=1 width\=39) (actual time\=0.237..0.237 rows\=1.00 loops\=340)|| |
| | 498 | || Index Cond: (event_id \= eh.event_id)|| |
| | 499 | || Index Searches: 340|| |
| | 500 | || Buffers: shared hit\=776 read\=244|| |
| | 501 | ||Planning:|| |
| | 502 | || Buffers: shared hit\=31 read\=8|| |
| | 503 | ||Planning Time: 0.659 ms|| |
| | 504 | ||Execution Time: 100.249 ms|| |
| | 505 | |
| | 506 | * '''INSERT''' |
| | 507 | |
| | 508 | {{{ |
| | 509 | |
| | 510 | EXPLAIN ANALYZE |
| | 511 | INSERT INTO "Event_Happening" (event_happening_id, event_id, venue_id, event_time, duration_minutes, organizers) |
| | 512 | VALUES (99999999, 1, 1, '2026-12-31 20:00:00', 120, 'Avalon Production'); |
| | 513 | |
| | 514 | }}} |
| | 515 | |
| | 516 | ||= QUERY PLAN =|| |
| | 517 | ||Insert on ""Event_Happening"" (cost\=0.00..0.01 rows\=0 width\=0) (actual time\=12.004..12.005 rows\=0.00 loops\=1)|| |
| | 518 | || Buffers: shared hit\=4 read\=5 dirtied\=1|| |
| | 519 | || -> Result (cost\=0.00..0.01 rows\=1 width\=100) (actual time\=0.002..0.003 rows\=1.00 loops\=1)|| |
| | 520 | ||Planning Time: 0.047 ms|| |
| | 521 | ||Trigger for constraint fk_happening_event: time\=0.276 calls\=1|| |
| | 522 | ||Trigger for constraint fk_happening_venue: time\=0.134 calls\=1|| |
| | 523 | ||Execution Time: 12.452 ms|| |
| | 524 | |
| | 525 | * '''UPDATE''' |
| | 526 | |
| | 527 | {{{ |
| | 528 | |
| | 529 | EXPLAIN ANALYZE |
| | 530 | UPDATE "Event_Happening" |
| | 531 | SET event_time = '2027-01-01 21:00:00' |
| | 532 | WHERE event_happening_id = 99999999; |
| | 533 | |
| | 534 | }}} |
| | 535 | |
| | 536 | ||= QUERY PLAN =|| |
| | 537 | ||Update on ""Event_Happening"" (cost\=0.29..8.30 rows\=0 width\=0) (actual time\=0.072..0.072 rows\=0.00 loops\=1)|| |
| | 538 | || Buffers: shared hit\=12|| |
| | 539 | || -> Index Scan using ""Event_Happening_pkey"" on ""Event_Happening"" (cost\=0.29..8.30 rows\=1 width\=14) (actual time\=0.023..0.024 rows\=1.00 loops\=1)|| |
| | 540 | || Index Cond: (event_happening_id \= 99999999)|| |
| | 541 | || Index Searches: 1|| |
| | 542 | || Buffers: shared hit\=3|| |
| | 543 | ||Planning Time: 0.089 ms|| |
| | 544 | ||Execution Time: 0.104 ms|| |
| | 545 | |
| | 546 | ==== 5. Оптимизација и индексирање: |
| | 547 | |
| | 548 | За да се елиминира потребата од пребарување на целата табела, креиравме '''B-tree''' индекс врз колоната `event_time`. Ова му овозможува на планерот да го лоцира временскиот „праг“ моментално. |
| | 549 | |
| | 550 | {{{ |
| | 551 | |
| | 552 | CREATE INDEX CONCURRENTLY idx_event_happening_time |
| | 553 | ON "Event_Happening" (event_time); |
| | 554 | |
| | 555 | |
| | 556 | ANALYZE "Event_Happening"; |
| | 557 | |
| | 558 | }}} |
| | 559 | |
| | 560 | ==== 6. Резултат по оптимизација: |
| | 561 | |
| | 562 | Со воведувањето на индексот, базата премина на '''Bitmap Index Scan''', што значи дека ја чита само релевантната мапа на записи наместо целиот диск. |
| | 563 | |
| | 564 | * Времето за '''SELECT''' падна на 8.451 ms, што е приближно 12 пати побрзо. |
| | 565 | * Времето за '''INSERT''' падна на 0.458 ms (околу 27 пати побрзо), бидејќи индексната структура се ажурира ефикасно. |
| | 566 | |
| | 567 | * '''SELECT''' |
| | 568 | |
| | 569 | {{{ |
| | 570 | |
| | 571 | EXPLAIN ANALYZE |
| | 572 | SELECT * FROM "Future_Events" |
| | 573 | WHERE city = 'Berlin'; |
| | 574 | |
| | 575 | }}} |
| | 576 | |
| | 577 | ||= QUERY PLAN =|| |
| | 578 | ||Nested Loop (cost\=509.90..1246.42 rows\=96 width\=121) (actual time\=2.527..8.451 rows\=114.00 loops\=1)|| |
| | 579 | || Buffers: shared hit\=981|| |
| | 580 | || -> Hash Join (cost\=509.62..1204.96 rows\=96 width\=90) (actual time\=2.504..7.880 rows\=114.00 loops\=1)|| |
| | 581 | || Hash Cond: (eh.venue_id \= v.venue_id)|| |
| | 582 | || Buffers: shared hit\=639|| |
| | 583 | || -> Bitmap Heap Scan on ""Event_Happening"" eh (cost\=248.69..910.02 rows\=12955 width\=32) (actual time\=0.722..3.795 rows\=12973.00 loops\=1)|| |
| | 584 | || Recheck Cond: (event_time > CURRENT_TIMESTAMP)|| |
| | 585 | || Heap Blocks: exact\=467|| |
| | 586 | || Buffers: shared hit\=504|| |
| | 587 | || -> Bitmap Index Scan on idx_event_happening_time (cost\=0.00..245.45 rows\=12955 width\=0) (actual time\=0.656..0.656 rows\=12976.00 loops\=1)|| |
| | 588 | || Index Cond: (event_time > CURRENT_TIMESTAMP)|| |
| | 589 | || Index Searches: 1|| |
| | 590 | || Buffers: shared hit\=37|| |
| | 591 | || -> Hash (cost\=260.00..260.00 rows\=74 width\=66) (actual time\=1.770..1.771 rows\=74.00 loops\=1)|| |
| | 592 | || Buckets: 1024 Batches: 1 Memory Usage: 15kB|| |
| | 593 | || Buffers: shared hit\=135|| |
| | 594 | || -> Seq Scan on ""Venue"" v (cost\=0.00..260.00 rows\=74 width\=66) (actual time\=0.011..1.739 rows\=74.00 loops\=1)|| |
| | 595 | || Filter: ((address_city)::text \= 'Berlin'::text)|| |
| | 596 | || Rows Removed by Filter: 9926|| |
| | 597 | || Buffers: shared hit\=135|| |
| | 598 | || -> Index Scan using ""Event_pkey"" on ""Event"" e (cost\=0.29..0.43 rows\=1 width\=39) (actual time\=0.004..0.004 rows\=1.00 loops\=114)|| |
| | 599 | || Index Cond: (event_id \= eh.event_id)|| |
| | 600 | || Index Searches: 114|| |
| | 601 | || Buffers: shared hit\=342|| |
| | 602 | ||Planning:|| |
| | 603 | || Buffers: shared hit\=40|| |
| | 604 | ||Planning Time: 0.547 ms|| |
| | 605 | ||Execution Time: 8.502 ms|| |
| | 606 | |
| | 607 | * '''INSERT''' |
| | 608 | |
| | 609 | {{{ |
| | 610 | |
| | 611 | EXPLAIN ANALYZE |
| | 612 | INSERT INTO "Event_Happening" (event_happening_id, event_id, venue_id, event_time, duration_minutes, organizers) |
| | 613 | VALUES (88888888, 1, 1, '2028-05-15 19:30:00', 90, 'Berlin Concerts GmbH'); |
| | 614 | |
| | 615 | }}} |
| | 616 | |
| | 617 | ||= QUERY PLAN =|| |
| | 618 | ||Insert on ""Event_Happening"" (cost\=0.00..0.01 rows\=0 width\=0) (actual time\=0.275..0.275 rows\=0.00 loops\=1)|| |
| | 619 | || Buffers: shared hit\=12 dirtied\=2|| |
| | 620 | || -> Result (cost\=0.00..0.01 rows\=1 width\=100) (actual time\=0.001..0.001 rows\=1.00 loops\=1)|| |
| | 621 | ||Planning Time: 0.031 ms|| |
| | 622 | ||Trigger for constraint fk_happening_event: time\=0.109 calls\=1|| |
| | 623 | ||Trigger for constraint fk_happening_venue: time\=0.058 calls\=1|| |
| | 624 | ||Execution Time: 0.458 ms|| |
| | 625 | |
| | 626 | * '''UPDATE''' |
| | 627 | |
| | 628 | {{{ |
| | 629 | |
| | 630 | EXPLAIN ANALYZE |
| | 631 | UPDATE "Event_Happening" |
| | 632 | SET event_time = '2028-05-16 20:00:00' |
| | 633 | WHERE event_happening_id = 88888888; |
| | 634 | |
| | 635 | }}} |
| | 636 | |
| | 637 | ||= QUERY PLAN =|| |
| | 638 | ||Update on ""Event_Happening"" (cost\=0.29..8.30 rows\=0 width\=0) (actual time\=0.073..0.073 rows\=0.00 loops\=1)|| |
| | 639 | || Buffers: shared hit\=14|| |
| | 640 | || -> Index Scan using ""Event_Happening_pkey"" on ""Event_Happening"" (cost\=0.29..8.30 rows\=1 width\=14) (actual time\=0.022..0.023 rows\=1.00 loops\=1)|| |
| | 641 | || Index Cond: (event_happening_id \= 88888888)|| |
| | 642 | || Index Searches: 1|| |
| | 643 | || Buffers: shared hit\=3|| |
| | 644 | ||Planning Time: 0.107 ms|| |
| | 645 | ||Execution Time: 0.119 ms|| |