Обсуждение: slow query

Поиск
Список
Период
Сортировка

slow query

От
Ayub Khan
Дата:

I checked all the indexes are defined on the tables however the query seems slow, below is the plan. Can any one give any pointers to verify ?
SELECT a.menu_item_id, a.menu_item_name, a.menu_item_category_id, b.menu_item_category_desc, c.menu_item_variant_id, c.menu_item_variant_type_id, c.price, c.size_id, c.parent_menu_item_variant_id, d.menu_item_variant_type_desc, e.size_desc, f.currency_code, a.image, a.mark_id, m.mark_name

 FROM menu_item_category AS b, menu_item_variant AS c, menu_item_variant_type AS d, item_size AS e, restaurant AS f, menu_item AS a

 LEFT OUTER JOIN mark AS m ON (a.mark_id = m.mark_id) WHERE a.menu_item_category_id = b.menu_item_category_id AND a.menu_item_id = c.menu_item_id AND c.menu_item_variant_type_id = d.menu_item_variant_type_id AND d.is_hidden = 'false' AND c.size_id = e.size_id AND a.restaurant_id = f.restaurant_id AND f.restaurant_id = 1528 AND (a.menu_item_category_id = NULL OR NULL IS NULL)

 AND c.menu_item_variant_id = (SELECT min(menu_item_variant_id) FROM menu_item_variant WHERE menu_item_id = a.menu_item_id AND deleted = 'N' limit 1) AND a.active = 'Y'
 AND (CONCAT_WS('', ',', a.hidden_branch_ids, ',') NOT LIKE CONCAT_WS('', '%,4191,%') OR NULL IS NULL)
 AND is_menu_item_available(a.menu_item_id, 'Y') = 'Y'

 ORDER BY a.row_order, menu_item_id;

below is the plan

Sort  (cost=189.27..189.27 rows=1 width=152) (actual time=5.876..5.885 rows=89 loops=1)
"  Sort Key: a.row_order, a.menu_item_id"
  Sort Method: quicksort  Memory: 48kB
  ->  Nested Loop Left Join  (cost=5.19..189.26 rows=1 width=152) (actual time=0.188..5.809 rows=89 loops=1)
        Join Filter: (a.mark_id = m.mark_id)
        Rows Removed by Join Filter: 267
        ->  Nested Loop  (cost=5.19..188.19 rows=1 width=148) (actual time=0.181..5.629 rows=89 loops=1)
              ->  Nested Loop  (cost=4.90..185.88 rows=1 width=152) (actual time=0.174..5.443 rows=89 loops=1)
                    ->  Nested Loop  (cost=4.61..185.57 rows=1 width=144) (actual time=0.168..5.272 rows=89 loops=1)
                          ->  Nested Loop  (cost=4.32..185.25 rows=1 width=136) (actual time=0.162..5.066 rows=89 loops=1)
                                ->  Nested Loop  (cost=0.71..179.62 rows=1 width=99) (actual time=0.137..3.986 rows=89 loops=1)
                                      ->  Index Scan using menu_item_restaurant_id on menu_item a  (cost=0.42..177.31 rows=1 width=87) (actual time=0.130..3.769 rows=89 loops=1)
                                            Index Cond: (restaurant_id = 1528)
"                                            Filter: ((active = 'Y'::bpchar) AND (is_menu_item_available(menu_item_id, 'Y'::bpchar) = 'Y'::bpchar))"
                                            Rows Removed by Filter: 194
                                      ->  Index Scan using menu_item_category_pk on menu_item_category b  (cost=0.29..2.31 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=89)
                                            Index Cond: (menu_item_category_id = a.menu_item_category_id)
                                ->  Index Scan using menu_item_variant_pk on menu_item_variant c  (cost=3.60..5.62 rows=1 width=45) (actual time=0.002..0.002 rows=1 loops=89)
                                      Index Cond: (menu_item_variant_id = (SubPlan 1))
                                      Filter: (a.menu_item_id = menu_item_id)
                                      SubPlan 1
                                        ->  Limit  (cost=3.17..3.18 rows=1 width=8) (actual time=0.009..0.009 rows=1 loops=89)
                                              ->  Aggregate  (cost=3.17..3.18 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=89)
                                                    ->  Index Scan using "idx$$_023a0001" on menu_item_variant  (cost=0.43..3.15 rows=8 width=8) (actual time=0.004..0.007 rows=7 loops=89)
                                                          Index Cond: (menu_item_id = a.menu_item_id)
                                                          Filter: (deleted = 'N'::bpchar)
                                                          Rows Removed by Filter: 4
                          ->  Index Scan using menu_item_variant_type_pk on menu_item_variant_type d  (cost=0.29..0.31 rows=1 width=16) (actual time=0.002..0.002 rows=1 loops=89)
                                Index Cond: (menu_item_variant_type_id = c.menu_item_variant_type_id)
                                Filter: ((is_hidden)::text = 'false'::text)
                    ->  Index Scan using size_pk on item_size e  (cost=0.29..0.31 rows=1 width=16) (actual time=0.001..0.001 rows=1 loops=89)
                          Index Cond: (size_id = c.size_id)
              ->  Index Scan using "restaurant_idx$$_274b003d" on restaurant f  (cost=0.29..2.30 rows=1 width=12) (actual time=0.001..0.002 rows=1 loops=89)
                    Index Cond: (restaurant_id = 1528)
        ->  Seq Scan on mark m  (cost=0.00..1.03 rows=3 width=12) (actual time=0.000..0.001 rows=3 loops=89)
Planning Time: 1.510 ms
Execution Time: 5.972 ms

Re: slow query

От
Christophe Pettus
Дата:

> On Jun 8, 2021, at 09:03, Ayub Khan <ayub.hp@gmail.com> wrote:
> I checked all the indexes are defined on the tables however the query seems slow, below is the plan.

It's currently running in slightly under six milliseconds.  That seems reasonably fast given the number of operations
requiredto fulfill it. 


Re: slow query

От
Ayub Khan
Дата:
In AWS RDS  performance insights the client writes is high and the api which receives data on the mobile side is slow during load test.

On Tue, 8 Jun 2021, 19:03 Ayub Khan, <ayub.hp@gmail.com> wrote:

I checked all the indexes are defined on the tables however the query seems slow, below is the plan. Can any one give any pointers to verify ?
SELECT a.menu_item_id, a.menu_item_name, a.menu_item_category_id, b.menu_item_category_desc, c.menu_item_variant_id, c.menu_item_variant_type_id, c.price, c.size_id, c.parent_menu_item_variant_id, d.menu_item_variant_type_desc, e.size_desc, f.currency_code, a.image, a.mark_id, m.mark_name

 FROM menu_item_category AS b, menu_item_variant AS c, menu_item_variant_type AS d, item_size AS e, restaurant AS f, menu_item AS a

 LEFT OUTER JOIN mark AS m ON (a.mark_id = m.mark_id) WHERE a.menu_item_category_id = b.menu_item_category_id AND a.menu_item_id = c.menu_item_id AND c.menu_item_variant_type_id = d.menu_item_variant_type_id AND d.is_hidden = 'false' AND c.size_id = e.size_id AND a.restaurant_id = f.restaurant_id AND f.restaurant_id = 1528 AND (a.menu_item_category_id = NULL OR NULL IS NULL)

 AND c.menu_item_variant_id = (SELECT min(menu_item_variant_id) FROM menu_item_variant WHERE menu_item_id = a.menu_item_id AND deleted = 'N' limit 1) AND a.active = 'Y'
 AND (CONCAT_WS('', ',', a.hidden_branch_ids, ',') NOT LIKE CONCAT_WS('', '%,4191,%') OR NULL IS NULL)
 AND is_menu_item_available(a.menu_item_id, 'Y') = 'Y'

 ORDER BY a.row_order, menu_item_id;

below is the plan

Sort  (cost=189.27..189.27 rows=1 width=152) (actual time=5.876..5.885 rows=89 loops=1)
"  Sort Key: a.row_order, a.menu_item_id"
  Sort Method: quicksort  Memory: 48kB
  ->  Nested Loop Left Join  (cost=5.19..189.26 rows=1 width=152) (actual time=0.188..5.809 rows=89 loops=1)
        Join Filter: (a.mark_id = m.mark_id)
        Rows Removed by Join Filter: 267
        ->  Nested Loop  (cost=5.19..188.19 rows=1 width=148) (actual time=0.181..5.629 rows=89 loops=1)
              ->  Nested Loop  (cost=4.90..185.88 rows=1 width=152) (actual time=0.174..5.443 rows=89 loops=1)
                    ->  Nested Loop  (cost=4.61..185.57 rows=1 width=144) (actual time=0.168..5.272 rows=89 loops=1)
                          ->  Nested Loop  (cost=4.32..185.25 rows=1 width=136) (actual time=0.162..5.066 rows=89 loops=1)
                                ->  Nested Loop  (cost=0.71..179.62 rows=1 width=99) (actual time=0.137..3.986 rows=89 loops=1)
                                      ->  Index Scan using menu_item_restaurant_id on menu_item a  (cost=0.42..177.31 rows=1 width=87) (actual time=0.130..3.769 rows=89 loops=1)
                                            Index Cond: (restaurant_id = 1528)
"                                            Filter: ((active = 'Y'::bpchar) AND (is_menu_item_available(menu_item_id, 'Y'::bpchar) = 'Y'::bpchar))"
                                            Rows Removed by Filter: 194
                                      ->  Index Scan using menu_item_category_pk on menu_item_category b  (cost=0.29..2.31 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=89)
                                            Index Cond: (menu_item_category_id = a.menu_item_category_id)
                                ->  Index Scan using menu_item_variant_pk on menu_item_variant c  (cost=3.60..5.62 rows=1 width=45) (actual time=0.002..0.002 rows=1 loops=89)
                                      Index Cond: (menu_item_variant_id = (SubPlan 1))
                                      Filter: (a.menu_item_id = menu_item_id)
                                      SubPlan 1
                                        ->  Limit  (cost=3.17..3.18 rows=1 width=8) (actual time=0.009..0.009 rows=1 loops=89)
                                              ->  Aggregate  (cost=3.17..3.18 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=89)
                                                    ->  Index Scan using "idx$$_023a0001" on menu_item_variant  (cost=0.43..3.15 rows=8 width=8) (actual time=0.004..0.007 rows=7 loops=89)
                                                          Index Cond: (menu_item_id = a.menu_item_id)
                                                          Filter: (deleted = 'N'::bpchar)
                                                          Rows Removed by Filter: 4
                          ->  Index Scan using menu_item_variant_type_pk on menu_item_variant_type d  (cost=0.29..0.31 rows=1 width=16) (actual time=0.002..0.002 rows=1 loops=89)
                                Index Cond: (menu_item_variant_type_id = c.menu_item_variant_type_id)
                                Filter: ((is_hidden)::text = 'false'::text)
                    ->  Index Scan using size_pk on item_size e  (cost=0.29..0.31 rows=1 width=16) (actual time=0.001..0.001 rows=1 loops=89)
                          Index Cond: (size_id = c.size_id)
              ->  Index Scan using "restaurant_idx$$_274b003d" on restaurant f  (cost=0.29..2.30 rows=1 width=12) (actual time=0.001..0.002 rows=1 loops=89)
                    Index Cond: (restaurant_id = 1528)
        ->  Seq Scan on mark m  (cost=0.00..1.03 rows=3 width=12) (actual time=0.000..0.001 rows=3 loops=89)
Planning Time: 1.510 ms
Execution Time: 5.972 ms

Re: slow query

От
Tom Lane
Дата:
Ayub Khan <ayub.hp@gmail.com> writes:
> I checked all the indexes are defined on the tables however the query seems
> slow, below is the plan. Can any one give any pointers to verify ?

You might try to do something about the poor selectivity estimate here:

>                                       ->  Index Scan using
> menu_item_restaurant_id on menu_item a  (cost=0.42..177.31 rows=1
> width=87) (actual time=0.130..3.769 rows=89 loops=1)
>                                             Index Cond: (restaurant_id = 1528)
> "                                            Filter: ((active =
> 'Y'::bpchar) AND (is_menu_item_available(menu_item_id, 'Y'::bpchar) =
> 'Y'::bpchar))"
>                                             Rows Removed by Filter: 194

If the planner realized that this'd produce O(100) rows not 1,
it'd likely have picked a different plan.  I'm guessing that
the issue is lack of knowledge about what is_menu_item_available()
will do.  Maybe you could replace that with a status column?

            regards, tom lane



Re: slow query

От
Ayub Khan
Дата:
below is function definition of is_menu_item_available,  for each item based on current day time it returns when it's available or not. The same api works fine on oracle, I am seeing this slowness after migrating the queries to postgresql RDS on AWS


CREATE OR REPLACE FUNCTION is_menu_item_available(
  i_menu_item_id bigint,
  i_check_availability character)
     RETURNS character
     LANGUAGE 'plpgsql'
     COST 100
     VOLATILE PARALLEL UNSAFE
 AS $BODY$
 DECLARE
     l_current_day NUMERIC(1);
     o_time CHARACTER VARYING(10);
     l_current_interval INTERVAL DAY TO SECOND(2);
     item_available_count NUMERIC(10);
 BEGIN
     item_available_count := 0;
 
     BEGIN
         IF i_check_availability = 'Y' THEN
             BEGIN
                 SELECT
                     CASE TO_CHAR(now(), 'fmday')
                         WHEN 'monday' THEN 1
                         WHEN 'tuesday' THEN 2
                         WHEN 'wednesday' THEN 3
                         WHEN 'thursday' THEN 4
                         WHEN 'friday' THEN 5
                         WHEN 'saturday' THEN 6
                         WHEN 'sunday' THEN 7
                     END AS d
                     INTO STRICT l_current_day;
               select (('0 ' ||
    EXTRACT (HOUR FROM ((now() at time zone 'UTC') at time zone '+03:00')) || ':' ||
      EXTRACT (minute FROM ((now() at time zone 'UTC') at time zone '+03:00')) || ':00') :: interval)
                         INTO l_current_interval;
 
             END;
 
             BEGIN
                 SELECT
                     COUNT(*)
                     INTO STRICT item_available_count
                     FROM menu_item_availability
                     WHERE menu_item_id = i_menu_item_id;
 
                 IF item_available_count = 0 THEN
                     RETURN 'Y';
                 ELSE
                     SELECT
     COUNT(*)
     INTO STRICT item_available_count
     FROM menu_item_availability AS mia, availability AS av
     WHERE mia.menu_item_id = i_menu_item_id
     AND mia.availability_id = av.id
     AND date_trunc('DAY',now()) + l_current_interval >= (CASE
         WHEN l_current_interval < '6 hour'::INTERVAL THEN date_trunc('DAY',now()) + av.start_time - (1::NUMERIC || ' days')::INTERVAL
         WHEN l_current_interval >= '6 hour'::INTERVAL THEN date_trunc('DAY',now())+ av.start_time
     END) AND date_trunc('DAY',now()) + l_current_interval <= (CASE
         WHEN l_current_interval < '6 hour'::INTERVAL THEN date_trunc('DAY',now()) + av.end_time - (1::NUMERIC || ' days')::INTERVAL
         WHEN l_current_interval >= '6 hour'::INTERVAL THEN date_trunc('DAY',now()) + av.end_time
     END) AND (av.day_of_week LIKE CONCAT_WS('', '%', l_current_day, '%') OR av.day_of_week LIKE '%0%') AND is_deleted = 0;
                 END IF;
             END;
 
             BEGIN
                 IF item_available_count > 0 THEN
                     RETURN 'Y';
                 ELSE
                     RETURN 'N';
                 END IF;
             END;
         ELSE
             RETURN 'Y';
         END IF;
     END;
 END;
 $BODY$;



On Tue, Jun 8, 2021 at 7:03 PM Ayub Khan <ayub.hp@gmail.com> wrote:

I checked all the indexes are defined on the tables however the query seems slow, below is the plan. Can any one give any pointers to verify ?
SELECT a.menu_item_id, a.menu_item_name, a.menu_item_category_id, b.menu_item_category_desc, c.menu_item_variant_id, c.menu_item_variant_type_id, c.price, c.size_id, c.parent_menu_item_variant_id, d.menu_item_variant_type_desc, e.size_desc, f.currency_code, a.image, a.mark_id, m.mark_name

 FROM menu_item_category AS b, menu_item_variant AS c, menu_item_variant_type AS d, item_size AS e, restaurant AS f, menu_item AS a

 LEFT OUTER JOIN mark AS m ON (a.mark_id = m.mark_id) WHERE a.menu_item_category_id = b.menu_item_category_id AND a.menu_item_id = c.menu_item_id AND c.menu_item_variant_type_id = d.menu_item_variant_type_id AND d.is_hidden = 'false' AND c.size_id = e.size_id AND a.restaurant_id = f.restaurant_id AND f.restaurant_id = 1528 AND (a.menu_item_category_id = NULL OR NULL IS NULL)

 AND c.menu_item_variant_id = (SELECT min(menu_item_variant_id) FROM menu_item_variant WHERE menu_item_id = a.menu_item_id AND deleted = 'N' limit 1) AND a.active = 'Y'
 AND (CONCAT_WS('', ',', a.hidden_branch_ids, ',') NOT LIKE CONCAT_WS('', '%,4191,%') OR NULL IS NULL)
 AND is_menu_item_available(a.menu_item_id, 'Y') = 'Y'

 ORDER BY a.row_order, menu_item_id;

below is the plan

Sort  (cost=189.27..189.27 rows=1 width=152) (actual time=5.876..5.885 rows=89 loops=1)
"  Sort Key: a.row_order, a.menu_item_id"
  Sort Method: quicksort  Memory: 48kB
  ->  Nested Loop Left Join  (cost=5.19..189.26 rows=1 width=152) (actual time=0.188..5.809 rows=89 loops=1)
        Join Filter: (a.mark_id = m.mark_id)
        Rows Removed by Join Filter: 267
        ->  Nested Loop  (cost=5.19..188.19 rows=1 width=148) (actual time=0.181..5.629 rows=89 loops=1)
              ->  Nested Loop  (cost=4.90..185.88 rows=1 width=152) (actual time=0.174..5.443 rows=89 loops=1)
                    ->  Nested Loop  (cost=4.61..185.57 rows=1 width=144) (actual time=0.168..5.272 rows=89 loops=1)
                          ->  Nested Loop  (cost=4.32..185.25 rows=1 width=136) (actual time=0.162..5.066 rows=89 loops=1)
                                ->  Nested Loop  (cost=0.71..179.62 rows=1 width=99) (actual time=0.137..3.986 rows=89 loops=1)
                                      ->  Index Scan using menu_item_restaurant_id on menu_item a  (cost=0.42..177.31 rows=1 width=87) (actual time=0.130..3.769 rows=89 loops=1)
                                            Index Cond: (restaurant_id = 1528)
"                                            Filter: ((active = 'Y'::bpchar) AND (is_menu_item_available(menu_item_id, 'Y'::bpchar) = 'Y'::bpchar))"
                                            Rows Removed by Filter: 194
                                      ->  Index Scan using menu_item_category_pk on menu_item_category b  (cost=0.29..2.31 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=89)
                                            Index Cond: (menu_item_category_id = a.menu_item_category_id)
                                ->  Index Scan using menu_item_variant_pk on menu_item_variant c  (cost=3.60..5.62 rows=1 width=45) (actual time=0.002..0.002 rows=1 loops=89)
                                      Index Cond: (menu_item_variant_id = (SubPlan 1))
                                      Filter: (a.menu_item_id = menu_item_id)
                                      SubPlan 1
                                        ->  Limit  (cost=3.17..3.18 rows=1 width=8) (actual time=0.009..0.009 rows=1 loops=89)
                                              ->  Aggregate  (cost=3.17..3.18 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=89)
                                                    ->  Index Scan using "idx$$_023a0001" on menu_item_variant  (cost=0.43..3.15 rows=8 width=8) (actual time=0.004..0.007 rows=7 loops=89)
                                                          Index Cond: (menu_item_id = a.menu_item_id)
                                                          Filter: (deleted = 'N'::bpchar)
                                                          Rows Removed by Filter: 4
                          ->  Index Scan using menu_item_variant_type_pk on menu_item_variant_type d  (cost=0.29..0.31 rows=1 width=16) (actual time=0.002..0.002 rows=1 loops=89)
                                Index Cond: (menu_item_variant_type_id = c.menu_item_variant_type_id)
                                Filter: ((is_hidden)::text = 'false'::text)
                    ->  Index Scan using size_pk on item_size e  (cost=0.29..0.31 rows=1 width=16) (actual time=0.001..0.001 rows=1 loops=89)
                          Index Cond: (size_id = c.size_id)
              ->  Index Scan using "restaurant_idx$$_274b003d" on restaurant f  (cost=0.29..2.30 rows=1 width=12) (actual time=0.001..0.002 rows=1 loops=89)
                    Index Cond: (restaurant_id = 1528)
        ->  Seq Scan on mark m  (cost=0.00..1.03 rows=3 width=12) (actual time=0.000..0.001 rows=3 loops=89)
Planning Time: 1.510 ms
Execution Time: 5.972 ms


--
--------------------------------------------------------------------
Sun Certified Enterprise Architect 1.5
Sun Certified Java Programmer 1.4
Microsoft Certified Systems Engineer 2000
http://in.linkedin.com/pub/ayub-khan/a/811/b81
mobile:+966-502674604
----------------------------------------------------------------------
It is proved that Hard Work and kowledge will get you close but attitude will get you there. However, it's the Love
of God that will put you over the top!!

Re: slow query

От
Jeff Janes
Дата:
On Tue, Jun 8, 2021 at 12:32 PM Ayub Khan <ayub.hp@gmail.com> wrote:
In AWS RDS  performance insights the client writes is high and the api which receives data on the mobile side is slow during load test.

That indicates a client or network problem.

Jeff

Re: slow query

От
Ayub Khan
Дата:
Below is the test setup

Jmeter-->(load balanced tomcat on ec2 instances)---->rds read replicas

All these are running on different ec2 instances in AWS cloud in the same region

On Tue, 8 Jun 2021, 19:03 Ayub Khan, <ayub.hp@gmail.com> wrote:

I checked all the indexes are defined on the tables however the query seems slow, below is the plan. Can any one give any pointers to verify ?
SELECT a.menu_item_id, a.menu_item_name, a.menu_item_category_id, b.menu_item_category_desc, c.menu_item_variant_id, c.menu_item_variant_type_id, c.price, c.size_id, c.parent_menu_item_variant_id, d.menu_item_variant_type_desc, e.size_desc, f.currency_code, a.image, a.mark_id, m.mark_name

 FROM menu_item_category AS b, menu_item_variant AS c, menu_item_variant_type AS d, item_size AS e, restaurant AS f, menu_item AS a

 LEFT OUTER JOIN mark AS m ON (a.mark_id = m.mark_id) WHERE a.menu_item_category_id = b.menu_item_category_id AND a.menu_item_id = c.menu_item_id AND c.menu_item_variant_type_id = d.menu_item_variant_type_id AND d.is_hidden = 'false' AND c.size_id = e.size_id AND a.restaurant_id = f.restaurant_id AND f.restaurant_id = 1528 AND (a.menu_item_category_id = NULL OR NULL IS NULL)

 AND c.menu_item_variant_id = (SELECT min(menu_item_variant_id) FROM menu_item_variant WHERE menu_item_id = a.menu_item_id AND deleted = 'N' limit 1) AND a.active = 'Y'
 AND (CONCAT_WS('', ',', a.hidden_branch_ids, ',') NOT LIKE CONCAT_WS('', '%,4191,%') OR NULL IS NULL)
 AND is_menu_item_available(a.menu_item_id, 'Y') = 'Y'

 ORDER BY a.row_order, menu_item_id;

below is the plan

Sort  (cost=189.27..189.27 rows=1 width=152) (actual time=5.876..5.885 rows=89 loops=1)
"  Sort Key: a.row_order, a.menu_item_id"
  Sort Method: quicksort  Memory: 48kB
  ->  Nested Loop Left Join  (cost=5.19..189.26 rows=1 width=152) (actual time=0.188..5.809 rows=89 loops=1)
        Join Filter: (a.mark_id = m.mark_id)
        Rows Removed by Join Filter: 267
        ->  Nested Loop  (cost=5.19..188.19 rows=1 width=148) (actual time=0.181..5.629 rows=89 loops=1)
              ->  Nested Loop  (cost=4.90..185.88 rows=1 width=152) (actual time=0.174..5.443 rows=89 loops=1)
                    ->  Nested Loop  (cost=4.61..185.57 rows=1 width=144) (actual time=0.168..5.272 rows=89 loops=1)
                          ->  Nested Loop  (cost=4.32..185.25 rows=1 width=136) (actual time=0.162..5.066 rows=89 loops=1)
                                ->  Nested Loop  (cost=0.71..179.62 rows=1 width=99) (actual time=0.137..3.986 rows=89 loops=1)
                                      ->  Index Scan using menu_item_restaurant_id on menu_item a  (cost=0.42..177.31 rows=1 width=87) (actual time=0.130..3.769 rows=89 loops=1)
                                            Index Cond: (restaurant_id = 1528)
"                                            Filter: ((active = 'Y'::bpchar) AND (is_menu_item_available(menu_item_id, 'Y'::bpchar) = 'Y'::bpchar))"
                                            Rows Removed by Filter: 194
                                      ->  Index Scan using menu_item_category_pk on menu_item_category b  (cost=0.29..2.31 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=89)
                                            Index Cond: (menu_item_category_id = a.menu_item_category_id)
                                ->  Index Scan using menu_item_variant_pk on menu_item_variant c  (cost=3.60..5.62 rows=1 width=45) (actual time=0.002..0.002 rows=1 loops=89)
                                      Index Cond: (menu_item_variant_id = (SubPlan 1))
                                      Filter: (a.menu_item_id = menu_item_id)
                                      SubPlan 1
                                        ->  Limit  (cost=3.17..3.18 rows=1 width=8) (actual time=0.009..0.009 rows=1 loops=89)
                                              ->  Aggregate  (cost=3.17..3.18 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=89)
                                                    ->  Index Scan using "idx$$_023a0001" on menu_item_variant  (cost=0.43..3.15 rows=8 width=8) (actual time=0.004..0.007 rows=7 loops=89)
                                                          Index Cond: (menu_item_id = a.menu_item_id)
                                                          Filter: (deleted = 'N'::bpchar)
                                                          Rows Removed by Filter: 4
                          ->  Index Scan using menu_item_variant_type_pk on menu_item_variant_type d  (cost=0.29..0.31 rows=1 width=16) (actual time=0.002..0.002 rows=1 loops=89)
                                Index Cond: (menu_item_variant_type_id = c.menu_item_variant_type_id)
                                Filter: ((is_hidden)::text = 'false'::text)
                    ->  Index Scan using size_pk on item_size e  (cost=0.29..0.31 rows=1 width=16) (actual time=0.001..0.001 rows=1 loops=89)
                          Index Cond: (size_id = c.size_id)
              ->  Index Scan using "restaurant_idx$$_274b003d" on restaurant f  (cost=0.29..2.30 rows=1 width=12) (actual time=0.001..0.002 rows=1 loops=89)
                    Index Cond: (restaurant_id = 1528)
        ->  Seq Scan on mark m  (cost=0.00..1.03 rows=3 width=12) (actual time=0.000..0.001 rows=3 loops=89)
Planning Time: 1.510 ms
Execution Time: 5.972 ms