slow query

2021-06-08 Thread 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)

Re: slow query

2021-06-08 Thread Christophe Pettus



> On Jun 8, 2021, at 09:03, Ayub Khan  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 required to fulfill it.



Re: slow query

2021-06-08 Thread 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,  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

Re: slow query

2021-06-08 Thread Tom Lane
Ayub Khan  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

2021-06-08 Thread 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  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..