1
votes

I am using Kaminari to paginate two sets of data on a page in my app. One set of data has around 620 records and the other around 150. So not many compared to some.

However, the pagination partials are taking around 900ms to load for each. See: 21:46:38 rails.1 | Rendered items/_paginator.erb (952.8ms)

Apparently this is due to a COUNT that Kaminari is doing. More details here: https://github.com/amatsuda/kaminari/issues/545

I have looked around, even here on SO and found similar questions and loads of answers on how to speed up COUNT but nothing in relation to speeding it up in tandem with Kaminari.

Any ideas on how to do this?

My terminal output for this request:

22:46:31 rails.1 |    (1.6ms)  SELECT COUNT(*) FROM "coasters" WHERE "coasters"."superseded_at" IS NULL AND (material = 'steel')
22:46:31 rails.1 |    (0.7ms)  SELECT COUNT(*) FROM "coasters" WHERE "coasters"."superseded_at" IS NULL AND (material = 'wood')
22:46:31 rails.1 |   Rendered shared/_breadcrumb_text.html.erb (9.6ms)
22:46:31 rails.1 |   Rendered shared/_fact_bar.html.erb (0.3ms)
22:46:32 rails.1 |   ParkChain Load (0.7ms)  SELECT "park_chains".* FROM "park_chains"
22:46:32 rails.1 |   Rendered theme_parks/parks/_filter_links.html.erb (11.5ms)
22:46:32 rails.1 |   Rendered theme_parks/coasters/_filter_links.html.erb (3.2ms)
22:46:33 rails.1 |    (0.4ms)  SELECT COUNT(*) FROM "parks"
22:46:33 rails.1 |   Rendered theme_parks/parks/_park_paginator.erb (1029.5ms)
22:46:33 rails.1 |   Park Load (1.2ms)  SELECT  "parks".* FROM "parks"  ORDER BY name ASC LIMIT 25 OFFSET 0
22:46:33 rails.1 |   Rendered theme_parks/parks/_park.html.erb (7.9ms)
22:46:33 rails.1 |   Rendered theme_parks/parks/_park_grid.html.erb (175.6ms)
22:46:34 rails.1 |   Rendered theme_parks/parks/_park_paginator.erb (961.1ms)
22:46:36 rails.1 |    (1.7ms)  SELECT COUNT(DISTINCT "coasters"."id") FROM "coasters" LEFT OUTER JOIN "parks" ON "parks"."id" = "coasters"."park_id" LEFT OUTER JOIN "cycles" ON "cycles"."coaster_id" = "coasters"."id" WHERE "coasters"."superseded_at" IS NULL
22:46:36 rails.1 |   Rendered theme_parks/coasters/_coaster_paginator.erb (1104.5ms)
22:46:36 rails.1 |   SQL (2.6ms)  SELECT  DISTINCT "coasters"."id", parks.name AS alias_0, coasters.name AS alias_1 FROM "coasters" LEFT OUTER JOIN "parks" ON "parks"."id" = "coasters"."park_id" LEFT OUTER JOIN "cycles" ON "cycles"."coaster_id" = "coasters"."id" WHERE "coasters"."superseded_at" IS NULL  ORDER BY parks.name ASC, coasters.name ASC LIMIT 25 OFFSET 0
22:46:36 rails.1 |   SQL (16.8ms)  SELECT "coasters"."id" AS t0_r0, "coasters"."name" AS t0_r1, "coasters"."inversions" AS t0_r2, "coasters"."material" AS t0_r3, "coasters"."notes" AS t0_r4, "coasters"."lat" AS t0_r5, "coasters"."lng" AS t0_r6, "coasters"."manufacturer_id" AS t0_r7, "coasters"."park_id" AS t0_r8, "coasters"."created_at" AS t0_r9, "coasters"."updated_at" AS t0_r10, "coasters"."slug" AS t0_r11, "coasters"."covering" AS t0_r12, "coasters"."style" AS t0_r13, "coasters"."model" AS t0_r14, "coasters"."layout" AS t0_r15, "coasters"."order_ridden" AS t0_r16, "coasters"."dates_ridden" AS t0_r17, "coasters"."on_ride_photo" AS t0_r18, "coasters"."powered" AS t0_r19, "coasters"."length" AS t0_r20, "coasters"."height" AS t0_r21, "coasters"."speed" AS t0_r22, "coasters"."coaster_sort" AS t0_r23, "coasters"."is_milestone" AS t0_r24, "coasters"."version_number" AS t0_r25, "coasters"."version_reason" AS t0_r26, "coasters"."version_ridden_after" AS t0_r27, "coasters"."position" AS t0_r28, "coasters"."relocated" AS t0_r29, "coasters"."renamed" AS t0_r30, "coasters"."rethemed" AS t0_r31, "coasters"."steel_10" AS t0_r32, "coasters"."wood_10" AS t0_r33, "coasters"."original_version_id" AS t0_r34, "coasters"."superseded_at" AS t0_r35, "parks"."id" AS t1_r0, "parks"."name" AS t1_r1, "parks"."location_1" AS t1_r2, "parks"."location_2" AS t1_r3, "parks"."location_3" AS t1_r4, "parks"."lat" AS t1_r5, "parks"."lng" AS t1_r6, "parks"."created_at" AS t1_r7, "parks"."updated_at" AS t1_r8, "parks"."location_4" AS t1_r9, "parks"."country" AS t1_r10, "parks"."park_chain_id" AS t1_r11, "parks"."notes" AS t1_r12, "parks"."visit_count" AS t1_r13, "parks"."dates_visited" AS t1_r14, "parks"."slug" AS t1_r15, "parks"."order_visited" AS t1_r16, "parks"."logo" AS t1_r17, "cycles"."id" AS t2_r0, "cycles"."coaster_id" AS t2_r1, "cycles"."notes" AS t2_r2, "cycles"."date" AS t2_r3, "cycles"."created_at" AS t2_r4, "cycles"."updated_at" AS t2_r5 FROM "coasters" LEFT OUTER JOIN "parks" ON "parks"."id" = "coasters"."park_id" LEFT OUTER JOIN "cycles" ON "cycles"."coaster_id" = "coasters"."id" WHERE "coasters"."superseded_at" IS NULL AND "coasters"."id" IN (21926, 22414, 21927, 21939, 21963, 21964, 21962, 21965, 21800, 21790, 21791, 21793, 21794, 21795, 22378, 21845, 21792, 21842, 21941, 22179, 22144, 22145, 22065, 22196, 22188)  ORDER BY parks.name ASC, coasters.name ASC
22:46:36 rails.1 |   Rendered theme_parks/coasters/_coaster.html.erb (273.5ms)
22:46:36 rails.1 |   Rendered theme_parks/coasters/_coaster_grid.html.erb (576.9ms)
22:46:37 rails.1 |   Rendered theme_parks/coasters/_coaster_paginator.erb (968.7ms)
22:46:37 rails.1 |   Rendered theme_parks/index.html.erb within layouts/application (6285.8ms)
22:46:38 rails.1 |   Rendered shared/_banner_slideshow.html.erb (0.1ms)
22:46:38 rails.1 |   Rendered shared/_flash_messages.html.erb (0.2ms)
22:46:38 rails.1 | Completed 200 OK in 7547ms (Views: 7216.3ms | ActiveRecord: 33.3ms)

UPDATE: enter image description here

1
If that single SQL call is taking almost 1 second to run there is something misconfigured with your database. I have a table with 570K rows and it takes 333ms. - Philip Hallstrom
@PhilipHallstrom ok. How would I find what is causing the slowdown on the DB end and to reconfigure it to be faster as I realise my number of records is nowhere near the amount others like yourself have. - rctneil
@PhilipHallstrom If I just run a standard COUNT query, it's really fast but when it's a part of Kaminari, then it's slow and the pagination render takes between 900 - 1000ms. So it's Kaminari but I can't find a solution to fix it. - rctneil
so it looks like there is a problem in coaster_paginator.erb, but _coaster.html.erb and _coaster_grid.html.erb are also rather slow. - Meier
Views: 7216.3ms | ActiveRecord: 33.3ms: your database appears to have nothing to do with it, actual interaction with the database is less than 0.5% of the total render time. There is something else slowing down the process. You may need a profiler to find it. - D-side

1 Answers

0
votes

I did some analysis. I have tested the rendering speed on PostgreSQL and MySQL is the same. After I optimised the query to 300ms, rendering was 2500-3500ms. There are two things that made my rendering much faster.

  1. I commented out gem 'bootstrap-kaminari-views', rendering decreased to 1000ms but it was ugly. If I copy erb files from that gem to my app/views/kaminari folder, I also get 1000ms and it looks good. That was a surprise.
  2. I tried .page(params[:page]).without_count and rendering decreased to 150ms. It is different type of pagination, so I have to think if it is suitable for my app.

BTW it was faster on Rails 4.2, now I am upgrading to 5.2 and have this problem.