| 328 | | === 4. Анализа на поглед 4, рангирање на артистите по слушања (популарност) во изминатите 30 дена === |
| 329 | | |
| 330 | | - Доколку сакаме да видиме како одреден артист се рангира во споредба со остнатите артисти, извршуваме: |
| 331 | | |
| 332 | | [[Image(View4_1.png, 800px)]] |
| 333 | | |
| 334 | | - Време потребно за пребарување: |
| 335 | | |
| 336 | | [[Image(View4_2.png, 800px)]] |
| 337 | | |
| 338 | | [[Image(View4_3.png, 800px)]] |
| 339 | | |
| 340 | | [[Image(View4_4.png, 800px)]] |
| 341 | | |
| 342 | | - **~5-6sec**. Бавната операција е секвенцијално пребарување на Song_streams табелата што би можеле да го оптимизираме со индекс: |
| 343 | | |
| 344 | | [[Image(View4_5.png, 800px)]] |
| 345 | | |
| 346 | | - Време на извршување **со индекс**: |
| 347 | | |
| 348 | | [[Image(View4_6.png, 800px)]] |
| 349 | | |
| 350 | | [[Image(View4_7.png, 800px)]] |
| 351 | | |
| 352 | | - **~2sec**. Со индекс добивме ~ 57% побрзо извршување. |
| 353 | | |
| 354 | | - Време потребно за внес на запис во Song_streams **без индекс**: |
| 355 | | |
| 356 | | [[Image(View4_8.png, 800px)]] |
| 357 | | |
| 358 | | [[Image(View4_9.png, 800px)]] |
| 359 | | |
| 360 | | - **0.2ms** |
| 361 | | |
| 362 | | - Време потребно за внес на запис во Song_streams со индекс: |
| 363 | | |
| 364 | | [[Image(View4_10.png, 800px)]] |
| 365 | | |
| 366 | | - **~3ms** |
| 367 | | |
| 368 | | - Време потребно за ажурирање запис во Song_streams **без индекс**: |
| 369 | | |
| 370 | | [[Image(View4_11.png, 800px)]] |
| 371 | | |
| 372 | | [[Image(View4_12.png, 800px)]] |
| 373 | | |
| 374 | | - **~0.7ms** |
| 375 | | |
| 376 | | - Време потребно за ажурирање запис во Song_streams **со индекс**: |
| 377 | | |
| 378 | | [[Image(View4_13.png, 800px)]] |
| 379 | | |
| 380 | | - **~0.2ms** |
| 381 | | |
| | 328 | === 4. Анализа на поглед 4, број на слушања (популарност) на артисте за изминатите 30 дена |
| | 329 | |
| | 330 | Прашалник кој ќе го тестираме: |
| | 331 | |
| | 332 | {{{ |
| | 333 | SELECT * FROM artist_popularity_last_30_days WHERE artist_display_name='Rush'; |
| | 334 | }}} |
| | 335 | |
| | 336 | ==== Време на извршување без индекси: |
| | 337 | |
| | 338 | **5295.544 ms** |
| | 339 | |
| | 340 | {{{ |
| | 341 | Subquery Scan on artist_popularity_last_30_days (cost=258658.87..261658.85 rows=500 width=60) (actual time=5248.277..5288.441 rows=41 loops=1) |
| | 342 | Filter: ((artist_popularity_last_30_days.artist_display_name)::text = 'Rush'::text) |
| | 343 | Rows Removed by Filter: 99959 |
| | 344 | -> WindowAgg (cost=258658.87..260408.85 rows=100000 width=60) (actual time=5247.481..5281.467 rows=100000 loops=1) |
| | 345 | -> Sort (cost=258658.85..258908.85 rows=100000 width=52) (actual time=5247.444..5253.777 rows=100000 loops=1) |
| | 346 | Sort Key: artist_listens.total_listens DESC |
| | 347 | Sort Method: quicksort Memory: 7706kB |
| | 348 | -> Subquery Scan on artist_listens (cost=249104.03..250354.03 rows=100000 width=52) (actual time=5163.853..5210.492 rows=100000 loops=1) |
| | 349 | -> HashAggregate (cost=249104.03..250354.03 rows=100000 width=52) (actual time=5163.847..5200.274 rows=100000 loops=1) |
| | 350 | Group Key: a.id |
| | 351 | Batches: 1 Memory Usage: 22545kB |
| | 352 | -> Hash Left Join (cost=173161.35..239347.87 rows=1951232 width=28) (actual time=3172.252..4602.821 rows=1953805 loops=1) |
| | 353 | Hash Cond: (s.id = sc.song_id) |
| | 354 | -> Hash Right Join (cost=3618.00..64682.53 rows=1951232 width=28) (actual time=123.141..1016.733 rows=1953805 loops=1) |
| | 355 | Hash Cond: (s.owner_artist_id = a.id) |
| | 356 | -> Seq Scan on songs s (cost=0.00..55942.32 rows=1951232 width=16) (actual time=70.738..304.609 rows=1951232 loops=1) |
| | 357 | -> Hash (cost=2368.00..2368.00 rows=100000 width=20) (actual time=52.166..52.167 rows=100000 loops=1) |
| | 358 | Buckets: 131072 Batches: 1 Memory Usage: 6157kB |
| | 359 | -> Seq Scan on artists a (cost=0.00..2368.00 rows=100000 width=20) (actual time=21.265..34.097 rows=100000 loops=1) |
| | 360 | -> Hash (cost=167349.12..167349.12 rows=175538 width=16) (actual time=3048.716..3048.831 rows=304092 loops=1) |
| | 361 | Buckets: 524288 (originally 262144) Batches: 1 (originally 1) Memory Usage: 18351kB |
| | 362 | -> Subquery Scan on sc (cost=163838.36..167349.12 rows=175538 width=16) (actual time=2861.695..2967.031 rows=304092 loops=1) |
| | 363 | -> Finalize HashAggregate (cost=163838.36..165593.74 rows=175538 width=16) (actual time=2861.688..2940.091 rows=304092 loops=1) |
| | 364 | Group Key: ss.song_id |
| | 365 | Batches: 1 Memory Usage: 36881kB |
| | 366 | -> Gather (cost=88357.02..160327.60 rows=702152 width=16) (actual time=2650.692..2751.352 rows=304092 loops=1) |
| | 367 | Workers Planned: 4 |
| | 368 | Workers Launched: 0 |
| | 369 | -> Partial HashAggregate (cost=87357.02..89112.40 rows=175538 width=16) (actual time=2650.252..2729.313 rows=304092 loops=1) |
| | 370 | Group Key: ss.song_id |
| | 371 | Batches: 1 Memory Usage: 36881kB |
| | 372 | -> Parallel Seq Scan on song_streams ss (cost=0.00..86108.61 rows=249682 width=8) (actual time=0.039..2307.530 rows=996439 loops=1) |
| | 373 | Filter: (streamed_at >= (CURRENT_TIMESTAMP - '30 days'::interval)) |
| | 374 | Rows Removed by Filter: 5779244 |
| | 375 | Planning Time: 0.601 ms |
| | 376 | JIT: |
| | 377 | Functions: 38 |
| | 378 | " Options: Inlining false, Optimization false, Expressions true, Deforming true" |
| | 379 | " Timing: Generation 2.191 ms (Deform 0.875 ms), Inlining 0.000 ms, Optimization 0.746 ms, Emission 20.211 ms, Total 23.149 ms" |
| | 380 | Execution Time: 5295.544 ms |
| | 381 | }}} |
| | 382 | |
| | 383 | Најбавните делови се секвенцијално скенирање на табелите {{{song_streams}}} и {{{songs}}}, што можеме да го оптимизираме со индекс: |
| | 384 | |
| | 385 | {{{ |
| | 386 | CREATE INDEX idx_song_streams_streamed_at_song_id ON song_streams(streamed_at, song_id); |
| | 387 | CREATE INDEX idx_songs_owner_artist_id ON songs(owner_artist_id); |
| | 388 | }}} |
| | 389 | |
| | 390 | ==== Време на извршување со индекси: |
| | 391 | |
| | 392 | **2923.180 ms** |
| | 393 | |
| | 394 | {{{ |
| | 395 | WindowAgg (cost=132657.36..134407.34 rows=100000 width=60) (actual time=2878.456..2912.811 rows=100000 loops=1) |
| | 396 | -> Sort (cost=132657.34..132907.34 rows=100000 width=52) (actual time=2878.421..2884.685 rows=100000 loops=1) |
| | 397 | Sort Key: artist_listens.total_listens DESC |
| | 398 | Sort Method: quicksort Memory: 7706kB |
| | 399 | -> Subquery Scan on artist_listens (cost=123102.52..124352.52 rows=100000 width=52) (actual time=2795.069..2840.462 rows=100000 loops=1) |
| | 400 | -> HashAggregate (cost=123102.52..124352.52 rows=100000 width=52) (actual time=2795.063..2830.225 rows=100000 loops=1) |
| | 401 | Group Key: a.id |
| | 402 | Batches: 1 Memory Usage: 22545kB |
| | 403 | -> Hash Left Join (cost=47159.84..113346.36 rows=1951232 width=28) (actual time=826.776..2239.576 rows=1953805 loops=1) |
| | 404 | Hash Cond: (s.id = sc.song_id) |
| | 405 | -> Hash Right Join (cost=3618.00..64682.53 rows=1951232 width=28) (actual time=118.783..1004.286 rows=1953805 loops=1) |
| | 406 | Hash Cond: (s.owner_artist_id = a.id) |
| | 407 | -> Seq Scan on songs s (cost=0.00..55942.32 rows=1951232 width=16) (actual time=69.772..303.956 rows=1951232 loops=1) |
| | 408 | -> Hash (cost=2368.00..2368.00 rows=100000 width=20) (actual time=48.780..48.781 rows=100000 loops=1) |
| | 409 | Buckets: 131072 Batches: 1 Memory Usage: 6157kB |
| | 410 | -> Seq Scan on artists a (cost=0.00..2368.00 rows=100000 width=20) (actual time=17.634..30.840 rows=100000 loops=1) |
| | 411 | -> Hash (cost=41347.61..41347.61 rows=175538 width=16) (actual time=707.572..707.574 rows=304102 loops=1) |
| | 412 | Buckets: 524288 (originally 262144) Batches: 1 (originally 1) Memory Usage: 18351kB |
| | 413 | -> Subquery Scan on sc (cost=37836.85..41347.61 rows=175538 width=16) (actual time=533.395..631.097 rows=304102 loops=1) |
| | 414 | -> HashAggregate (cost=37836.85..39592.23 rows=175538 width=16) (actual time=533.387..597.876 rows=304102 loops=1) |
| | 415 | Group Key: ss.song_id |
| | 416 | Batches: 1 Memory Usage: 36881kB |
| | 417 | -> Index Only Scan using idx_song_streams_streamed_at_song_id on song_streams ss (cost=0.44..32842.98 rows=998774 width=8) (actual time=0.057..245.680 rows=996484 loops=1) |
| | 418 | Index Cond: (streamed_at >= (CURRENT_TIMESTAMP - '30 days'::interval)) |
| | 419 | Heap Fetches: 0 |
| | 420 | Planning Time: 0.573 ms |
| | 421 | JIT: |
| | 422 | Functions: 32 |
| | 423 | " Options: Inlining false, Optimization false, Expressions true, Deforming true" |
| | 424 | " Timing: Generation 2.147 ms (Deform 0.709 ms), Inlining 0.000 ms, Optimization 0.652 ms, Emission 16.640 ms, Total 19.439 ms" |
| | 425 | Execution Time: 2923.180 ms |
| | 426 | }}} |
| | 427 | |
| | 428 | Сега планерот го користи креираниот индекс за табелата {{{song_streams}}}, но сепак табелата {{{songs}}} треба секвенцијално да се скенира за да се пресмета статистиката за артистите. Дополнителна оптимизација правиме со материјализиран поглед: |
| | 429 | |
| | 430 | {{{ |
| | 431 | CREATE MATERIALIZED VIEW artist_popularity_last_30_days_mv AS |
| | 432 | WITH streams_count AS ( |
| | 433 | SELECT ss.song_id, COUNT(*) AS cnt |
| | 434 | FROM song_streams ss |
| | 435 | WHERE ss.streamed_at >= CURRENT_TIMESTAMP - INTERVAL '30 days' |
| | 436 | GROUP BY ss.song_id |
| | 437 | ), |
| | 438 | artist_listens AS ( |
| | 439 | SELECT |
| | 440 | a.id AS artist_id, |
| | 441 | a.display_name AS artist_display_name, |
| | 442 | COALESCE(SUM(sc.cnt), 0) AS total_listens |
| | 443 | FROM artists a |
| | 444 | LEFT JOIN songs s ON s.owner_artist_id = a.id |
| | 445 | LEFT JOIN streams_count sc ON sc.song_id = s.id |
| | 446 | GROUP BY a.id, a.display_name |
| | 447 | ) |
| | 448 | SELECT |
| | 449 | ROW_NUMBER() OVER (ORDER BY total_listens DESC) AS rank, |
| | 450 | artist_id, |
| | 451 | artist_display_name, |
| | 452 | total_listens |
| | 453 | FROM artist_listens; |
| | 454 | |
| | 455 | }}} |
| | 456 | |
| | 457 | ==== Време за извршување на прашалникот по додавање на материјализиран поглед |
| | 458 | |
| | 459 | {{{ |
| | 460 | Seq Scan on artist_popularity_last_30_days_mv (cost=0.00..2082.00 rows=2 width=31) (actual time=0.210..9.704 rows=41 loops=1) |
| | 461 | Filter: ((artist_display_name)::text = 'Rush'::text) |
| | 462 | Rows Removed by Filter: 99959 |
| | 463 | Planning Time: 0.094 ms |
| | 464 | Execution Time: 9.731 ms |
| | 465 | }}} |
| | 466 | |
| | 467 | Со материјализиран поглед добиваме <10 ms за читање. |
| | 468 | |
| | 469 | === 5. Анализа на поглед 5, број на слушања (популарност) на песните за изминатите 30 дена |
| | 470 | |
| | 471 | Прашалник кој ќе го тестираме: |
| | 472 | |
| | 473 | {{{ |
| | 474 | SELECT * FROM most_popular_songs_last_30_days WHERE rank=15; |
| | 475 | }}} |
| | 476 | |
| | 477 | ==== Време за извршување со креираниот индекс {{{idx_song_streams_streamed_at_song_id}}} |
| | 478 | |
| | 479 | **1682.017 ms** |
| | 480 | |
| | 481 | {{{ |
| | 482 | Subquery Scan on most_popular_songs_last_30_days (cost=96713.63..122558.33 rows=878 width=96) (actual time=1471.660..1677.911 rows=1 loops=1) |
| | 483 | Filter: (most_popular_songs_last_30_days.rank = 17) |
| | 484 | Rows Removed by Filter: 16 |
| | 485 | -> WindowAgg (cost=96713.63..120364.14 rows=175535 width=96) (actual time=1471.640..1677.902 rows=17 loops=1) |
| | 486 | Run Condition: (row_number() OVER (?) <= 17) |
| | 487 | -> Gather Merge (cost=96713.50..117731.12 rows=175535 width=88) (actual time=1471.591..1677.843 rows=18 loops=1) |
| | 488 | Workers Planned: 4 |
| | 489 | Workers Launched: 4 |
| | 490 | -> Sort (cost=95713.44..95823.15 rows=43884 width=88) (actual time=1433.450..1433.565 rows=564 loops=5) |
| | 491 | Sort Key: sc.total_streams DESC |
| | 492 | Sort Method: quicksort Memory: 9470kB |
| | 493 | Worker 0: Sort Method: quicksort Memory: 9145kB |
| | 494 | Worker 1: Sort Method: quicksort Memory: 2511kB |
| | 495 | Worker 2: Sort Method: quicksort Memory: 2431kB |
| | 496 | Worker 3: Sort Method: quicksort Memory: 9520kB |
| | 497 | -> Parallel Hash Join (cost=49328.85..92329.67 rows=43884 width=88) (actual time=1114.045..1407.397 rows=60789 loops=5) |
| | 498 | Hash Cond: (s.owner_artist_id = a.id) |
| | 499 | -> Hash Left Join (cost=46637.31..89522.94 rows=43884 width=84) (actual time=1076.395..1343.191 rows=60789 loops=5) |
| | 500 | Hash Cond: (s.published_by_label_admin_id = la.id) |
| | 501 | -> Hash Join (cost=43501.50..86090.08 rows=43884 width=48) (actual time=1071.308..1327.862 rows=60789 loops=5) |
| | 502 | Hash Cond: (s.id = sc.song_id) |
| | 503 | -> Parallel Seq Scan on songs s (cost=0.00..41308.08 rows=487808 width=40) (actual time=0.092..135.322 rows=390246 loops=5) |
| | 504 | -> Hash (cost=41307.31..41307.31 rows=175535 width=16) (actual time=1069.687..1069.689 rows=303945 loops=5) |
| | 505 | Buckets: 524288 (originally 262144) Batches: 1 (originally 1) Memory Usage: 18344kB |
| | 506 | -> Subquery Scan on sc (cost=37796.61..41307.31 rows=175535 width=16) (actual time=837.380..966.924 rows=303945 loops=5) |
| | 507 | -> HashAggregate (cost=37796.61..39551.96 rows=175535 width=16) (actual time=837.372..937.795 rows=303945 loops=5) |
| | 508 | Group Key: song_streams.song_id |
| | 509 | Batches: 1 Memory Usage: 36881kB |
| | 510 | Worker 0: Batches: 1 Memory Usage: 36881kB |
| | 511 | Worker 1: Batches: 1 Memory Usage: 36881kB |
| | 512 | Worker 2: Batches: 1 Memory Usage: 36881kB |
| | 513 | Worker 3: Batches: 1 Memory Usage: 36881kB |
| | 514 | -> Index Only Scan using idx_song_streams_streamed_at_song_id on song_streams (cost=0.44..32809.02 rows=997519 width=8) (actual time=0.137..407.430 rows=995226 loops=5) |
| | 515 | Index Cond: (streamed_at >= (CURRENT_TIMESTAMP - '30 days'::interval)) |
| | 516 | Heap Fetches: 95 |
| | 517 | -> Hash (cost=3131.12..3131.12 rows=375 width=48) (actual time=4.957..4.961 rows=375 loops=5) |
| | 518 | Buckets: 1024 Batches: 1 Memory Usage: 38kB |
| | 519 | -> Nested Loop Left Join (cost=13.86..3131.12 rows=375 width=48) (actual time=0.389..4.675 rows=375 loops=5) |
| | 520 | -> Hash Left Join (cost=13.44..21.18 rows=375 width=39) (actual time=0.317..0.558 rows=375 loops=5) |
| | 521 | Hash Cond: (la.label_id = l.id) |
| | 522 | -> Seq Scan on label_admins la (cost=0.00..6.75 rows=375 width=24) (actual time=0.068..0.157 rows=375 loops=5) |
| | 523 | -> Hash (cost=8.75..8.75 rows=375 width=31) (actual time=0.214..0.215 rows=375 loops=5) |
| | 524 | Buckets: 1024 Batches: 1 Memory Usage: 33kB |
| | 525 | -> Seq Scan on labels l (cost=0.00..8.75 rows=375 width=31) (actual time=0.051..0.109 rows=375 loops=5) |
| | 526 | -> Index Scan using users_pkey on users u (cost=0.42..8.29 rows=1 width=25) (actual time=0.010..0.010 rows=1 loops=1875) |
| | 527 | Index Cond: (id = la.user_id) |
| | 528 | -> Parallel Hash (cost=1956.24..1956.24 rows=58824 width=20) (actual time=37.138..37.139 rows=20000 loops=5) |
| | 529 | Buckets: 131072 Batches: 1 Memory Usage: 6528kB |
| | 530 | -> Parallel Seq Scan on artists a (cost=0.00..1956.24 rows=58824 width=20) (actual time=27.866..30.351 rows=20000 loops=5) |
| | 531 | Planning Time: 1.492 ms |
| | 532 | JIT: |
| | 533 | Functions: 235 |
| | 534 | " Options: Inlining false, Optimization false, Expressions true, Deforming true" |
| | 535 | " Timing: Generation 14.075 ms (Deform 6.062 ms), Inlining 0.000 ms, Optimization 5.950 ms, Emission 133.686 ms, Total 153.711 ms" |
| | 536 | Execution Time: 1682.017 ms |
| | 537 | }}} |
| | 538 | |
| | 539 | За дополнителна оптимизација креираме материјализиран поглед: |
| | 540 | |
| | 541 | {{{ |
| | 542 | CREATE MATERIALIZED VIEW most_popular_songs_last_30_days_mv AS |
| | 543 | WITH stream_counts AS ( |
| | 544 | SELECT |
| | 545 | song_id, |
| | 546 | COUNT(*) AS total_streams |
| | 547 | FROM song_streams |
| | 548 | WHERE streamed_at >= CURRENT_TIMESTAMP - INTERVAL '30 days' |
| | 549 | GROUP BY song_id |
| | 550 | ) |
| | 551 | SELECT |
| | 552 | ROW_NUMBER() OVER (ORDER BY sc.total_streams DESC) AS rank, |
| | 553 | s.id AS song_id, |
| | 554 | s.title AS song_title, |
| | 555 | a.display_name AS artist_display_name, |
| | 556 | s.visibility AS song_visibility, |
| | 557 | u.username AS label_admin_username, |
| | 558 | l.name AS label_name, |
| | 559 | sc.total_streams |
| | 560 | FROM stream_counts sc |
| | 561 | JOIN songs s ON s.id = sc.song_id |
| | 562 | JOIN artists a ON s.owner_artist_id = a.id |
| | 563 | LEFT JOIN label_admins la ON s.published_by_label_admin_id = la.id |
| | 564 | LEFT JOIN labels l ON l.id = la.label_id |
| | 565 | LEFT JOIN users u ON u.id = la.user_id; |
| | 566 | }}} |
| | 567 | |
| | 568 | ==== Време за извршување на прашалникот по додавање на материјализиран поглед |
| | 569 | |
| | 570 | {{{ |
| | 571 | Gather (cost=1000.00..6167.16 rows=1 width=96) (actual time=0.381..671.251 rows=1 loops=1) |
| | 572 | Workers Planned: 2 |
| | 573 | Workers Launched: 2 |
| | 574 | -> Parallel Seq Scan on most_popular_songs_last_30_days_mv (cost=0.00..5167.06 rows=1 width=96) (actual time=417.275..638.156 rows=0 loops=3) |
| | 575 | Filter: (rank = 17) |
| | 576 | Rows Removed by Filter: 101315 |
| | 577 | Planning Time: 0.218 ms |
| | 578 | Execution Time: 671.277 ms |
| | 579 | }}} |
| | 580 | |
| | 581 | Со материјализиран поглед добиваме <1s време на читање. |
| | 582 | |
| | 583 | |
| | 584 | === 6. Анализа на поглед 6, детален преглед за артистите групирани по издавачка куќа на која припаѓаат |
| | 585 | |
| | 586 | Го тестираме прашалникот: |
| | 587 | |
| | 588 | {{{ SELECT * FROM label_artists_info WHERE label_name='Piercing Abyss Records';}}} |
| | 589 | |
| | 590 | |
| | 591 | ==== Време за извршување без индекси |
| | 592 | |
| | 593 | **3197.076 ms** |
| | 594 | |
| | 595 | {{{ |
| | 596 | Subquery Scan on label_artists_info (cost=48955.19..49185.03 rows=1561 width=51) (actual time=3166.576..3196.926 rows=81 loops=1) |
| | 597 | -> GroupAggregate (cost=48955.19..49169.42 rows=1561 width=59) (actual time=3166.575..3196.914 rows=81 loops=1) |
| | 598 | Group Key: a.id |
| | 599 | -> Gather Merge (cost=48955.19..49142.10 rows=1561 width=59) (actual time=3166.542..3196.531 rows=1660 loops=1) |
| | 600 | Workers Planned: 4 |
| | 601 | Workers Launched: 4 |
| | 602 | -> Sort (cost=47955.14..47956.11 rows=390 width=59) (actual time=2548.301..2548.327 rows=332 loops=5) |
| | 603 | " Sort Key: a.id, s.id" |
| | 604 | Sort Method: quicksort Memory: 68kB |
| | 605 | Worker 0: Sort Method: quicksort Memory: 35kB |
| | 606 | Worker 1: Sort Method: quicksort Memory: 39kB |
| | 607 | Worker 2: Sort Method: quicksort Memory: 44kB |
| | 608 | Worker 3: Sort Method: quicksort Memory: 60kB |
| | 609 | -> Nested Loop Left Join (cost=3303.17..47938.35 rows=390 width=59) (actual time=254.314..2547.203 rows=332 loops=5) |
| | 610 | -> Hash Join (cost=3302.88..47724.69 rows=390 width=59) (actual time=202.108..1249.756 rows=328 loops=5) |
| | 611 | Hash Cond: (a.id = al.artist_id) |
| | 612 | -> Parallel Hash Right Join (cost=2691.54..45280.17 rows=487808 width=36) (actual time=42.618..1060.686 rows=390761 loops=5) |
| | 613 | Hash Cond: (s.owner_artist_id = a.id) |
| | 614 | -> Parallel Seq Scan on songs s (cost=0.00..41308.08 rows=487808 width=16) (actual time=0.371..871.469 rows=390246 loops=5) |
| | 615 | -> Parallel Hash (cost=1956.24..1956.24 rows=58824 width=28) (actual time=41.753..41.754 rows=20000 loops=5) |
| | 616 | Buckets: 131072 Batches: 1 Memory Usage: 7328kB |
| | 617 | -> Parallel Seq Scan on artists a (cost=0.00..1956.24 rows=58824 width=28) (actual time=3.800..28.812 rows=20000 loops=5) |
| | 618 | -> Hash (cost=610.34..610.34 rows=80 width=31) (actual time=152.360..152.362 rows=81 loops=5) |
| | 619 | Buckets: 1024 Batches: 1 Memory Usage: 14kB |
| | 620 | -> Hash Join (cost=9.70..610.34 rows=80 width=31) (actual time=51.681..152.281 rows=81 loops=5) |
| | 621 | Hash Cond: (al.label_id = l.id) |
| | 622 | -> Seq Scan on artist_labels al (cost=0.00..521.00 rows=30000 width=16) (actual time=11.763..115.238 rows=30000 loops=5) |
| | 623 | -> Hash (cost=9.69..9.69 rows=1 width=31) (actual time=33.047..33.048 rows=1 loops=5) |
| | 624 | Buckets: 1024 Batches: 1 Memory Usage: 9kB |
| | 625 | -> Seq Scan on labels l (cost=0.00..9.69 rows=1 width=31) (actual time=32.998..33.038 rows=1 loops=5) |
| | 626 | Filter: ((name)::text = 'Piercing Abyss Records'::text) |
| | 627 | Rows Removed by Filter: 374 |
| | 628 | -> Index Scan using idx_follows_followed_user_id on follows f (cost=0.29..0.47 rows=8 width=16) (actual time=3.764..3.959 rows=1 loops=1638) |
| | 629 | Index Cond: (followed_user_id = a.user_id) |
| | 630 | Planning Time: 1776.191 ms |
| | 631 | Execution Time: 3197.076 ms |
| | 632 | }}} |
| | 633 | |
| | 634 | За да го оптимизираме секвенцијалното скенирање на табелите {{{songs}}} и {{{artist_labels}}}, ги креираме индексите: |
| | 635 | |
| | 636 | {{{ |
| | 637 | CREATE INDEX idx_songs_owner_artist_id ON songs(owner_artist_id); |
| | 638 | CREATE INDEX idx_artist_labels_label_id_artist_id ON artist_labels(label_id, artist_id); |
| | 639 | }}} |
| | 640 | |
| | 641 | ==== Време за извршување со индекси |
| | 642 | |
| | 643 | **5.213 ms** |
| | 644 | |
| | 645 | {{{ |
| | 646 | Subquery Scan on label_artists_info (cost=571.17..618.00 rows=1561 width=51) (actual time=4.634..5.127 rows=81 loops=1) |
| | 647 | -> GroupAggregate (cost=571.17..602.39 rows=1561 width=59) (actual time=4.633..5.116 rows=81 loops=1) |
| | 648 | Group Key: a.id |
| | 649 | -> Sort (cost=571.17..575.07 rows=1561 width=59) (actual time=4.614..4.708 rows=1660 loops=1) |
| | 650 | " Sort Key: a.id, s.id" |
| | 651 | Sort Method: quicksort Memory: 171kB |
| | 652 | -> Nested Loop Left Join (cost=6.04..488.37 rows=1561 width=59) (actual time=0.125..3.388 rows=1660 loops=1) |
| | 653 | -> Nested Loop Left Join (cost=5.62..274.33 rows=80 width=51) (actual time=0.115..0.973 rows=83 loops=1) |
| | 654 | -> Nested Loop (cost=5.32..230.51 rows=80 width=51) (actual time=0.105..0.685 rows=81 loops=1) |
| | 655 | -> Nested Loop (cost=4.91..175.24 rows=80 width=31) (actual time=0.092..0.265 rows=81 loops=1) |
| | 656 | -> Seq Scan on labels l (cost=0.00..9.69 rows=1 width=31) (actual time=0.051..0.075 rows=1 loops=1) |
| | 657 | Filter: ((name)::text = 'Piercing Abyss Records'::text) |
| | 658 | Rows Removed by Filter: 374 |
| | 659 | -> Bitmap Heap Scan on artist_labels al (cost=4.91..164.75 rows=80 width=16) (actual time=0.038..0.174 rows=81 loops=1) |
| | 660 | Recheck Cond: (l.id = label_id) |
| | 661 | Heap Blocks: exact=72 |
| | 662 | -> Bitmap Index Scan on idx_artist_labels_label_id_artist_id (cost=0.00..4.89 rows=80 width=0) (actual time=0.019..0.019 rows=81 loops=1) |
| | 663 | Index Cond: (label_id = l.id) |
| | 664 | -> Index Scan using artists_pkey on artists a (cost=0.42..0.69 rows=1 width=28) (actual time=0.005..0.005 rows=1 loops=81) |
| | 665 | Index Cond: (id = al.artist_id) |
| | 666 | -> Index Scan using idx_follows_followed_user_id on follows f (cost=0.29..0.47 rows=8 width=16) (actual time=0.003..0.003 rows=1 loops=81) |
| | 667 | Index Cond: (followed_user_id = a.user_id) |
| | 668 | -> Index Scan using idx_songs_owner_artist_id on songs s (cost=0.43..2.42 rows=26 width=16) (actual time=0.004..0.026 rows=20 loops=83) |
| | 669 | Index Cond: (owner_artist_id = a.id) |
| | 670 | Planning Time: 1.229 ms |
| | 671 | Execution Time: 5.213 ms |
| | 672 | }}} |
| | 673 | |
| | 674 | Планерот го користи и претходно креираниот индекс {{{idx_follows_followed_user_id}}}. Индексите го забрзаа извршувањето за речиси 100%, па заклучуваме дека нема потреба од дополнителна оптимизација. |
| | 675 | |
| | 676 | |
| | 677 | === 7. Анализа на поглед 7, детални информации за секоја песна |
| | 678 | |
| | 679 | Прашалник кој го тестираме: |
| | 680 | |
| | 681 | {{{ |
| | 682 | SELECT * FROM songs_details WHERE title='Harmony'; |
| | 683 | }}} |
| | 684 | |
| | 685 | ==== Време за извршување без индекси |
| | 686 | |
| | 687 | **93882.201 ms** |
| | 688 | |
| | 689 | {{{ |
| | 690 | Gather (cost=230200.46..235882.48 rows=2211 width=121) (actual time=3427.813..93875.377 rows=1683 loops=1) |
| | 691 | Workers Planned: 3 |
| | 692 | Workers Launched: 3 |
| | 693 | -> Nested Loop Left Join (cost=229200.46..234661.38 rows=713 width=121) (actual time=3393.680..41801.988 rows=421 loops=4) |
| | 694 | -> Merge Left Join (cost=229200.03..229252.13 rows=713 width=85) (actual time=3393.619..3396.837 rows=421 loops=4) |
| | 695 | Merge Cond: (s.id = pc.song_id) |
| | 696 | -> Sort (cost=225567.13..225568.91 rows=713 width=77) (actual time=3342.494..3342.739 rows=421 loops=4) |
| | 697 | Sort Key: s.id |
| | 698 | Sort Method: quicksort Memory: 48kB |
| | 699 | Worker 0: Sort Method: quicksort Memory: 44kB |
| | 700 | Worker 1: Sort Method: quicksort Memory: 44kB |
| | 701 | Worker 2: Sort Method: quicksort Memory: 72kB |
| | 702 | -> Nested Loop Left Join (cost=209283.95..225533.34 rows=713 width=77) (actual time=3254.123..3342.167 rows=421 loops=4) |
| | 703 | -> Parallel Hash Right Join (cost=209283.53..225211.18 rows=713 width=72) (actual time=3254.061..3337.679 rows=421 loops=4) |
| | 704 | Hash Cond: (at.song_id = s.id) |
| | 705 | -> Parallel Seq Scan on album_tracks at (cost=0.00..14292.12 rows=435812 width=16) (actual time=0.016..39.432 rows=337754 loops=4) |
| | 706 | -> Parallel Hash (cost=209276.62..209276.62 rows=553 width=64) (actual time=3253.381..3253.392 rows=421 loops=4) |
| | 707 | Buckets: 4096 Batches: 1 Memory Usage: 192kB |
| | 708 | -> Hash Left Join (cost=164727.43..209276.62 rows=553 width=64) (actual time=3174.557..3252.826 rows=421 loops=4) |
| | 709 | Hash Cond: (s.id = sc.song_id) |
| | 710 | -> Hash Left Join (cost=909.90..45457.64 rows=553 width=56) (actual time=52.511..130.411 rows=421 loops=4) |
| | 711 | Hash Cond: (al.label_id = l.id) |
| | 712 | -> Hash Left Join (cost=896.46..45442.74 rows=553 width=41) (actual time=52.297..129.994 rows=421 loops=4) |
| | 713 | Hash Cond: (a.id = al.artist_id) |
| | 714 | -> Nested Loop Left Join (cost=0.42..44542.96 rows=553 width=41) (actual time=41.010..118.277 rows=421 loops=4) |
| | 715 | -> Parallel Seq Scan on songs s (cost=0.00..42527.60 rows=553 width=29) (actual time=40.894..112.485 rows=421 loops=4) |
| | 716 | Filter: ((title)::text = 'Harmony'::text) |
| | 717 | Rows Removed by Filter: 487388 |
| | 718 | -> Index Scan using artists_pkey on artists a (cost=0.42..3.64 rows=1 width=20) (actual time=0.012..0.012 rows=1 loops=1683) |
| | 719 | Index Cond: (id = s.owner_artist_id) |
| | 720 | -> Hash (cost=521.02..521.02 rows=30002 width=16) (actual time=11.075..11.076 rows=30003 loops=4) |
| | 721 | Buckets: 32768 Batches: 1 Memory Usage: 1663kB |
| | 722 | -> Seq Scan on artist_labels al (cost=0.00..521.02 rows=30002 width=16) (actual time=0.053..4.694 rows=30003 loops=4) |
| | 723 | -> Hash (cost=8.75..8.75 rows=375 width=31) (actual time=0.190..0.191 rows=375 loops=4) |
| | 724 | Buckets: 1024 Batches: 1 Memory Usage: 33kB |
| | 725 | -> Seq Scan on labels l (cost=0.00..8.75 rows=375 width=31) (actual time=0.030..0.089 rows=375 loops=4) |
| | 726 | -> Hash (cost=161618.58..161618.58 rows=175916 width=16) (actual time=3120.501..3120.503 rows=635893 loops=4) |
| | 727 | Buckets: 1048576 (originally 262144) Batches: 1 (originally 1) Memory Usage: 38000kB |
| | 728 | -> Subquery Scan on sc (cost=158100.26..161618.58 rows=175916 width=16) (actual time=2662.167..2922.708 rows=635893 loops=4) |
| | 729 | -> HashAggregate (cost=158100.26..159859.42 rows=175916 width=16) (actual time=2662.160..2862.916 rows=635893 loops=4) |
| | 730 | Group Key: song_streams.song_id |
| | 731 | Batches: 1 Memory Usage: 65553kB |
| | 732 | Worker 0: Batches: 1 Memory Usage: 65553kB |
| | 733 | Worker 1: Batches: 1 Memory Usage: 65553kB |
| | 734 | Worker 2: Batches: 1 Memory Usage: 65553kB |
| | 735 | -> Seq Scan on song_streams (cost=0.00..124221.84 rows=6775684 width=8) (actual time=0.040..834.432 rows=6775685 loops=4) |
| | 736 | -> Index Scan using albums_pkey on albums alb (cost=0.42..0.45 rows=1 width=21) (actual time=0.010..0.010 rows=1 loops=1683) |
| | 737 | Index Cond: (id = at.album_id) |
| | 738 | -> Sort (cost=3632.91..3657.15 rows=9698 width=16) (actual time=51.065..52.559 rows=10235 loops=4) |
| | 739 | Sort Key: pc.song_id |
| | 740 | Sort Method: quicksort Memory: 706kB |
| | 741 | Worker 0: Sort Method: quicksort Memory: 706kB |
| | 742 | Worker 1: Sort Method: quicksort Memory: 706kB |
| | 743 | Worker 2: Sort Method: quicksort Memory: 706kB |
| | 744 | -> Subquery Scan on pc (cost=2796.77..2990.73 rows=9698 width=16) (actual time=45.054..47.748 rows=10288 loops=4) |
| | 745 | -> HashAggregate (cost=2796.77..2893.75 rows=9698 width=16) (actual time=45.048..46.739 rows=10288 loops=4) |
| | 746 | Group Key: playlist_tracks.song_id |
| | 747 | Batches: 1 Memory Usage: 1425kB |
| | 748 | Worker 0: Batches: 1 Memory Usage: 1425kB |
| | 749 | Worker 1: Batches: 1 Memory Usage: 1425kB |
| | 750 | Worker 2: Batches: 1 Memory Usage: 1425kB |
| | 751 | -> Seq Scan on playlist_tracks (cost=0.00..2171.18 rows=125118 width=8) (actual time=0.038..14.065 rows=125118 loops=4) |
| | 752 | -> Index Scan using idx_sag_mv_song_id on song_average_grade_mv sag (cost=0.43..7.58 rows=1 width=24) (actual time=91.275..91.276 rows=1 loops=1683) |
| | 753 | Index Cond: (song_id = s.id) |
| | 754 | Planning Time: 2.976 ms |
| | 755 | JIT: |
| | 756 | Functions: 272 |
| | 757 | " Options: Inlining false, Optimization false, Expressions true, Deforming true" |
| | 758 | " Timing: Generation 16.724 ms (Deform 7.604 ms), Inlining 0.000 ms, Optimization 6.390 ms, Emission 157.809 ms, Total 180.923 ms" |
| | 759 | Execution Time: 93882.201 ms |
| | 760 | }}} |
| | 761 | |
| | 762 | За оптимизирање на секвенцијалните скенирање на табелите {{{artist_labels}}}, {{{album_tracks}}} и {{{songs}}} ги креираме индексите: |
| | 763 | |
| | 764 | {{{ |
| | 765 | CREATE INDEX idx_songs_title |
| | 766 | ON songs(title); |
| | 767 | |
| | 768 | CREATE INDEX idx_album_tracks_song_id |
| | 769 | ON album_tracks(song_id); |
| | 770 | |
| | 771 | CREATE INDEX idx_artist_labels_artist_id |
| | 772 | ON artist_labels(artist_id); |
| | 773 | }}} |
| | 774 | |
| | 775 | ==== Време за извршување со индекси |
| | 776 | |
| | 777 | **3599.404 ms** |
| | 778 | |
| | 779 | {{{ |
| | 780 | Gather (cost=188600.68..198746.59 rows=2211 width=121) (actual time=3136.649..3592.763 rows=1683 loops=1) |
| | 781 | Workers Planned: 1 |
| | 782 | Workers Launched: 1 |
| | 783 | -> Nested Loop Left Join (cost=187600.68..197525.49 rows=1301 width=121) (actual time=3114.199..3121.952 rows=842 loops=2) |
| | 784 | -> Merge Left Join (cost=187600.25..187655.31 rows=1301 width=85) (actual time=3114.146..3116.186 rows=842 loops=2) |
| | 785 | Merge Cond: (s.id = pc.song_id) |
| | 786 | -> Sort (cost=183967.34..183970.60 rows=1301 width=77) (actual time=3064.947..3065.100 rows=842 loops=2) |
| | 787 | Sort Key: s.id |
| | 788 | Sort Method: quicksort Memory: 143kB |
| | 789 | Worker 0: Sort Method: quicksort Memory: 40kB |
| | 790 | -> Hash Left Join (cost=166553.22..183900.05 rows=1301 width=77) (actual time=3047.496..3064.384 rows=842 loops=2) |
| | 791 | Hash Cond: (s.id = sc.song_id) |
| | 792 | -> Nested Loop Left Join (cost=2735.67..20079.09 rows=1301 width=69) (actual time=64.333..80.679 rows=842 loops=2) |
| | 793 | -> Nested Loop Left Join (cost=2735.25..19491.26 rows=1301 width=64) (actual time=64.294..76.539 rows=842 loops=2) |
| | 794 | -> Hash Left Join (cost=2734.82..10204.79 rows=1301 width=56) (actual time=64.235..70.862 rows=842 loops=2) |
| | 795 | Hash Cond: (al.label_id = l.id) |
| | 796 | -> Nested Loop Left Join (cost=2721.39..10187.90 rows=1301 width=41) (actual time=64.055..70.410 rows=842 loops=2) |
| | 797 | -> Parallel Hash Left Join (cost=2721.10..9762.21 rows=1301 width=41) (actual time=64.004..67.464 rows=842 loops=2) |
| | 798 | Hash Cond: (s.owner_artist_id = a.id) |
| | 799 | -> Parallel Bitmap Heap Scan on songs s (cost=29.56..7067.26 rows=1301 width=29) (actual time=0.629..2.990 rows=842 loops=2) |
| | 800 | Recheck Cond: ((title)::text = 'Harmony'::text) |
| | 801 | Heap Blocks: exact=1395 |
| | 802 | -> Bitmap Index Scan on idx_songs_title (cost=0.00..29.01 rows=2211 width=0) (actual time=0.323..0.324 rows=1683 loops=1) |
| | 803 | Index Cond: ((title)::text = 'Harmony'::text) |
| | 804 | -> Parallel Hash (cost=1956.24..1956.24 rows=58824 width=20) (actual time=62.392..62.393 rows=50000 loops=2) |
| | 805 | Buckets: 131072 Batches: 1 Memory Usage: 6496kB |
| | 806 | -> Parallel Seq Scan on artists a (cost=0.00..1956.24 rows=58824 width=20) (actual time=38.029..44.369 rows=50000 loops=2) |
| | 807 | -> Index Scan using idx_artist_labels_artist_id on artist_labels al (cost=0.29..0.32 rows=1 width=16) (actual time=0.003..0.003 rows=0 loops=1683) |
| | 808 | Index Cond: (artist_id = a.id) |
| | 809 | -> Hash (cost=8.75..8.75 rows=375 width=31) (actual time=0.155..0.155 rows=375 loops=2) |
| | 810 | Buckets: 1024 Batches: 1 Memory Usage: 33kB |
| | 811 | -> Seq Scan on labels l (cost=0.00..8.75 rows=375 width=31) (actual time=0.031..0.079 rows=375 loops=2) |
| | 812 | -> Index Scan using idx_album_tracks_song_id on album_tracks at (cost=0.43..7.13 rows=1 width=16) (actual time=0.006..0.006 rows=1 loops=1683) |
| | 813 | Index Cond: (song_id = s.id) |
| | 814 | -> Index Scan using albums_pkey on albums alb (cost=0.42..0.45 rows=1 width=21) (actual time=0.004..0.004 rows=1 loops=1683) |
| | 815 | Index Cond: (id = at.album_id) |
| | 816 | -> Hash (cost=161618.60..161618.60 rows=175916 width=16) (actual time=2982.071..2982.073 rows=635893 loops=2) |
| | 817 | Buckets: 1048576 (originally 262144) Batches: 1 (originally 1) Memory Usage: 38000kB |
| | 818 | -> Subquery Scan on sc (cost=158100.27..161618.60 rows=175916 width=16) (actual time=2526.994..2790.788 rows=635893 loops=2) |
| | 819 | -> HashAggregate (cost=158100.27..159859.43 rows=175916 width=16) (actual time=2526.987..2726.430 rows=635893 loops=2) |
| | 820 | Group Key: song_streams.song_id |
| | 821 | Batches: 1 Memory Usage: 65553kB |
| | 822 | Worker 0: Batches: 1 Memory Usage: 65553kB |
| | 823 | -> Seq Scan on song_streams (cost=0.00..124221.85 rows=6775685 width=8) (actual time=0.049..708.679 rows=6775685 loops=2) |
| | 824 | -> Sort (cost=3632.91..3657.15 rows=9698 width=16) (actual time=49.155..49.933 rows=10235 loops=2) |
| | 825 | Sort Key: pc.song_id |
| | 826 | Sort Method: quicksort Memory: 706kB |
| | 827 | Worker 0: Sort Method: quicksort Memory: 706kB |
| | 828 | -> Subquery Scan on pc (cost=2796.77..2990.73 rows=9698 width=16) (actual time=43.313..46.006 rows=10288 loops=2) |
| | 829 | -> HashAggregate (cost=2796.77..2893.75 rows=9698 width=16) (actual time=43.307..44.952 rows=10288 loops=2) |
| | 830 | Group Key: playlist_tracks.song_id |
| | 831 | Batches: 1 Memory Usage: 1425kB |
| | 832 | Worker 0: Batches: 1 Memory Usage: 1425kB |
| | 833 | -> Seq Scan on playlist_tracks (cost=0.00..2171.18 rows=125118 width=8) (actual time=0.039..13.544 rows=125118 loops=2) |
| | 834 | -> Index Scan using idx_sag_mv_song_id on song_average_grade_mv sag (cost=0.43..7.58 rows=1 width=24) (actual time=0.006..0.006 rows=1 loops=1683) |
| | 835 | Index Cond: (song_id = s.id) |
| | 836 | Planning Time: 3.163 ms |
| | 837 | JIT: |
| | 838 | Functions: 132 |
| | 839 | " Options: Inlining false, Optimization false, Expressions true, Deforming true" |
| | 840 | " Timing: Generation 7.561 ms (Deform 3.504 ms), Inlining 0.000 ms, Optimization 2.789 ms, Emission 73.213 ms, Total 83.563 ms" |
| | 841 | Execution Time: 3599.404 ms |
| | 842 | }}} |
| | 843 | |
| | 844 | Бидејќи сепак имаме секвенцијално скенирање на табелата {{{song_streams}}} поради групирањето на слушања по песна, дополнително оптимизираме со материјализиран погледи: |
| | 845 | |
| | 846 | {{{ |
| | 847 | create materialized view song_stream_counts_mv as |
| | 848 | select |
| | 849 | song_id, |
| | 850 | count(*) as streams |
| | 851 | from song_streams |
| | 852 | group by song_id; |
| | 853 | |
| | 854 | |
| | 855 | create materialized view song_playlist_counts_mv as |
| | 856 | select |
| | 857 | song_id, |
| | 858 | count(*) as saved_in_playlists |
| | 859 | from playlist_tracks |
| | 860 | group by song_id; |
| | 861 | |
| | 862 | |
| | 863 | create or replace view song_detailed_info_view_mvs as |
| | 864 | select |
| | 865 | s.title as title, |
| | 866 | a.display_name as artist_name, |
| | 867 | coalesce(l.name, 'SOLO') as label_name, |
| | 868 | coalesce(sc.streams, 0) as streams, |
| | 869 | coalesce(alb.title, 'SINGLE') as album_title, |
| | 870 | coalesce(pc.saved_in_playlists, 0) as saved_in_playlists, |
| | 871 | sag.num_reviews, |
| | 872 | ROUND(sag.avg_grade, 2) AS avg_grade |
| | 873 | from songs s |
| | 874 | left join artists a on a.id = s.owner_artist_id |
| | 875 | left join artist_labels al on al.artist_id = a.id |
| | 876 | left join labels l on l.id = al.label_id |
| | 877 | left join album_tracks at on at.song_id = s.id |
| | 878 | left join albums alb on alb.id = at.album_id |
| | 879 | left join song_stream_counts_mv sc on sc.song_id = s.id |
| | 880 | left join song_playlist_counts_mv pc on pc.song_id = s.id |
| | 881 | left join song_average_grade_mv sag on sag.song_id = s.id; |
| | 882 | }}} |
| | 883 | |
| | 884 | |
| | 885 | ==== Време за извршување на прашалникот по додавање на материјализирани погледи |
| | 886 | |
| | 887 | **333.811 ms** |
| | 888 | |
| | 889 | {{{ |
| | 890 | Gather (cost=25188.45..57377.30 rows=2211 width=145) (actual time=113.872..333.525 rows=1683 loops=1) |
| | 891 | Workers Planned: 3 |
| | 892 | Workers Launched: 3 |
| | 893 | -> Parallel Hash Right Join (cost=24188.45..56156.20 rows=713 width=145) (actual time=84.308..207.282 rows=421 loops=4) |
| | 894 | Hash Cond: (sag.song_id = s.id) |
| | 895 | -> Parallel Seq Scan on song_average_grade_mv sag (cost=0.00..29616.74 rows=625674 width=24) (actual time=0.016..50.181 rows=484897 loops=4) |
| | 896 | -> Parallel Hash (cost=24176.94..24176.94 rows=921 width=85) (actual time=83.322..83.338 rows=421 loops=4) |
| | 897 | Buckets: 4096 Batches: 1 Memory Usage: 256kB |
| | 898 | -> Hash Left Join (cost=10077.11..24176.94 rows=921 width=85) (actual time=20.990..64.447 rows=421 loops=4) |
| | 899 | Hash Cond: (s.id = pc.song_id) |
| | 900 | -> Nested Loop Left Join (cost=9789.63..23885.95 rows=921 width=77) (actual time=17.300..60.507 rows=421 loops=4) |
| | 901 | -> Nested Loop Left Join (cost=9789.21..23469.82 rows=921 width=72) (actual time=17.283..57.817 rows=421 loops=4) |
| | 902 | -> Hash Left Join (cost=9788.78..16895.77 rows=921 width=64) (actual time=17.245..53.588 rows=421 loops=4) |
| | 903 | Hash Cond: (al.label_id = l.id) |
| | 904 | -> Nested Loop Left Join (cost=9775.35..16879.89 rows=921 width=49) (actual time=17.040..53.223 rows=421 loops=4) |
| | 905 | -> Parallel Hash Left Join (cost=9775.06..16578.54 rows=921 width=49) (actual time=16.984..51.378 rows=421 loops=4) |
| | 906 | Hash Cond: (s.owner_artist_id = a.id) |
| | 907 | -> Parallel Hash Right Join (cost=7083.52..13884.59 rows=921 width=37) (actual time=4.483..38.155 rows=421 loops=4) |
| | 908 | Hash Cond: (sc.song_id = s.id) |
| | 909 | -> Parallel Seq Scan on song_stream_counts_mv sc (cost=0.00..6105.55 rows=264955 width=16) (actual time=0.013..14.911 rows=158973 loops=4) |
| | 910 | -> Parallel Hash (cost=7067.26..7067.26 rows=1301 width=29) (actual time=4.275..4.276 rows=421 loops=4) |
| | 911 | Buckets: 4096 Batches: 1 Memory Usage: 160kB |
| | 912 | -> Parallel Bitmap Heap Scan on songs s (cost=29.56..7067.26 rows=1301 width=29) (actual time=0.718..3.921 rows=421 loops=4) |
| | 913 | Recheck Cond: ((title)::text = 'Harmony'::text) |
| | 914 | Heap Blocks: exact=455 |
| | 915 | -> Bitmap Index Scan on idx_songs_title (cost=0.00..29.01 rows=2211 width=0) (actual time=0.386..0.386 rows=1683 loops=1) |
| | 916 | Index Cond: ((title)::text = 'Harmony'::text) |
| | 917 | -> Parallel Hash (cost=1956.24..1956.24 rows=58824 width=20) (actual time=12.017..12.018 rows=25000 loops=4) |
| | 918 | Buckets: 131072 Batches: 1 Memory Usage: 6528kB |
| | 919 | -> Parallel Seq Scan on artists a (cost=0.00..1956.24 rows=58824 width=20) (actual time=0.166..3.968 rows=25000 loops=4) |
| | 920 | -> Index Scan using idx_artist_labels_artist_id on artist_labels al (cost=0.29..0.32 rows=1 width=16) (actual time=0.004..0.004 rows=0 loops=1683) |
| | 921 | Index Cond: (artist_id = a.id) |
| | 922 | -> Hash (cost=8.75..8.75 rows=375 width=31) (actual time=0.179..0.180 rows=375 loops=4) |
| | 923 | Buckets: 1024 Batches: 1 Memory Usage: 33kB |
| | 924 | -> Seq Scan on labels l (cost=0.00..8.75 rows=375 width=31) (actual time=0.030..0.078 rows=375 loops=4) |
| | 925 | -> Index Scan using idx_album_tracks_song_id on album_tracks at (cost=0.43..7.13 rows=1 width=16) (actual time=0.009..0.009 rows=1 loops=1683) |
| | 926 | Index Cond: (song_id = s.id) |
| | 927 | -> Index Scan using albums_pkey on albums alb (cost=0.42..0.45 rows=1 width=21) (actual time=0.006..0.006 rows=1 loops=1683) |
| | 928 | Index Cond: (id = at.album_id) |
| | 929 | -> Hash (cost=158.88..158.88 rows=10288 width=16) (actual time=3.568..3.568 rows=10288 loops=4) |
| | 930 | Buckets: 16384 Batches: 1 Memory Usage: 611kB |
| | 931 | -> Seq Scan on song_playlist_counts_mv pc (cost=0.00..158.88 rows=10288 width=16) (actual time=0.022..1.349 rows=10288 loops=4) |
| | 932 | Planning Time: 135.345 ms |
| | 933 | Execution Time: 333.811 ms |
| | 934 | }}} |
| | 935 | |
| | 936 | |
| | 937 | === 8. Анализа на поглед 8, историја на слушање песни од корисниците |
| | 938 | |
| | 939 | Прашалник кој го тестираме: |
| | 940 | |
| | 941 | {{{ |
| | 942 | SELECT * |
| | 943 | FROM streams_history |
| | 944 | WHERE username='adriana_klein_511' |
| | 945 | ORDER BY streamed_at DESC; |
| | 946 | }}} |
| | 947 | |
| | 948 | ==== Време за извршување без дополнителни индекси |
| | 949 | |
| | 950 | **0.404 ms** |
| | 951 | |
| | 952 | {{{ |
| | 953 | Sort (cost=52.13..52.15 rows=7 width=58) (actual time=0.333..0.335 rows=15 loops=1) |
| | 954 | Sort Key: ss.streamed_at DESC |
| | 955 | Sort Method: quicksort Memory: 26kB |
| | 956 | -> Nested Loop (cost=1.72..52.03 rows=7 width=58) (actual time=0.072..0.316 rows=15 loops=1) |
| | 957 | -> Nested Loop (cost=1.28..48.40 rows=7 width=62) (actual time=0.061..0.195 rows=15 loops=1) |
| | 958 | -> Nested Loop (cost=0.86..45.09 rows=7 width=49) (actual time=0.049..0.094 rows=15 loops=1) |
| | 959 | -> Index Scan using users_username_key on users u (cost=0.42..8.44 rows=1 width=25) (actual time=0.029..0.030 rows=1 loops=1) |
| | 960 | Index Cond: ((username)::text = 'adriana_klein_511'::text) |
| | 961 | -> Index Scan using idx_song_streams_user_id on song_streams ss (cost=0.43..36.57 rows=8 width=32) (actual time=0.014..0.056 rows=15 loops=1) |
| | 962 | Index Cond: (user_id = u.id) |
| | 963 | -> Index Scan using songs_pkey on songs s (cost=0.43..0.47 rows=1 width=21) (actual time=0.006..0.006 rows=1 loops=15) |
| | 964 | Index Cond: (id = ss.song_id) |
| | 965 | -> Index Scan using playback_sessions_pkey on playback_sessions ps (cost=0.43..0.52 rows=1 width=12) (actual time=0.007..0.007 rows=1 loops=15) |
| | 966 | Index Cond: (id = ss.playback_session_id) |
| | 967 | Planning Time: 91.388 ms |
| | 968 | Execution Time: 0.404 ms |
| | 969 | }}} |
| | 970 | |
| | 971 | Бидејќи се корситат индексите креирани за примарните клучеви, како и индексот {{{ idx_song_streams_user_id }}}, нема потреба за дополнителна оптимизација на прашалникот |