Переглянути джерело

feat: optimize SQL queries with Subquery First strategy and add execution timers

lanfr144 1 тиждень тому
батько
коміт
9dbc74e194
1 змінених файлів з 28 додано та 14 видалено
  1. 28 14
      app.py

+ 28 - 14
app.py

@@ -430,28 +430,35 @@ with tab_explore:
                 with conn_reader.cursor() as cursor:
                     l_str = "" if limit_rc == "All" else f"LIMIT {limit_rc}"
                     query = f"""
-                        SELECT c.code, MAX(c.product_name) as product_name, MAX(c.generic_name) as generic_name, MAX(c.brands) as brands, MAX(c.ingredients_text) as ingredients_text,
+                        SELECT c.code, c.product_name, MAX(c.generic_name) as generic_name, MAX(c.brands) as brands, MAX(c.ingredients_text) as ingredients_text,
                                MAX(a.allergens) as allergens,
                                MAX(m.`energy-kcal_100g`) as `energy-kcal_100g`, MAX(m.proteins_100g) as proteins_100g, MAX(m.fat_100g) as fat_100g, MAX(m.carbohydrates_100g) as carbohydrates_100g, MAX(m.sugars_100g) as sugars_100g, MAX(m.fiber_100g) as fiber_100g, MAX(m.sodium_100g) as sodium_100g, MAX(m.salt_100g) as salt_100g, MAX(m.cholesterol_100g) as cholesterol_100g,
                                MAX(v.`vitamin-a_100g`) as `vitamin-a_100g`, MAX(v.`vitamin-b1_100g`) as `vitamin-b1_100g`, MAX(v.`vitamin-b2_100g`) as `vitamin-b2_100g`, MAX(v.`vitamin-pp_100g`) as `vitamin-pp_100g`, MAX(v.`vitamin-b6_100g`) as `vitamin-b6_100g`, MAX(v.`vitamin-b9_100g`) as `vitamin-b9_100g`, MAX(v.`vitamin-b12_100g`) as `vitamin-b12_100g`, MAX(v.`vitamin-c_100g`) as `vitamin-c_100g`, MAX(v.`vitamin-d_100g`) as `vitamin-d_100g`, MAX(v.`vitamin-e_100g`) as `vitamin-e_100g`, MAX(v.`vitamin-k_100g`) as `vitamin-k_100g`,
                                MAX(min.calcium_100g) as calcium_100g, MAX(min.iron_100g) as iron_100g, MAX(min.magnesium_100g) as magnesium_100g, MAX(min.potassium_100g) as potassium_100g, MAX(min.zinc_100g) as zinc_100g
-                        FROM food_db.products_core c
+                        FROM (
+                            SELECT code, MAX(product_name) as product_name, MAX(generic_name) as generic_name, MAX(brands) as brands, MAX(ingredients_text) as ingredients_text
+                            FROM food_db.products_core
+                            WHERE MATCH(product_name, ingredients_text) AGAINST(%s IN BOOLEAN MODE)
+                            AND product_name IS NOT NULL AND product_name != '' AND product_name != 'None'
+                            GROUP BY code
+                            {l_str}
+                        ) c
                         LEFT JOIN food_db.products_allergens a ON c.code = a.code
                         LEFT JOIN food_db.products_macros m ON c.code = m.code
                         LEFT JOIN food_db.products_vitamins v ON c.code = v.code
                         LEFT JOIN food_db.products_minerals min ON c.code = min.code
-                        WHERE MATCH(c.product_name, c.ingredients_text) AGAINST(%s IN BOOLEAN MODE)
-                        AND c.product_name IS NOT NULL AND c.product_name != '' AND c.product_name != 'None'
-                        AND (m.proteins_100g >= %s OR m.proteins_100g IS NULL)
+                        WHERE (m.proteins_100g >= %s OR m.proteins_100g IS NULL)
                         AND (m.fat_100g >= %s OR m.fat_100g IS NULL)
                         AND (m.carbohydrates_100g >= %s OR m.carbohydrates_100g IS NULL)
                         AND (m.sugars_100g <= %s OR m.sugars_100g IS NULL)
-                        GROUP BY c.code
-                        {l_str}
+                        GROUP BY c.code, c.product_name
                     """
                     sq_bool = " ".join([f"+{w}" for w in sq.split()])
+                    start_time = time.time()
                     cursor.execute(query, (sq_bool, min_pro, min_fat, min_carb, max_sug))
                     results = cursor.fetchall()
+                    elapsed = time.time() - start_time
+                    st.caption(f"⏱️ DB Query Executed in {elapsed:.3f} seconds")
                     
                     if results:
                         # Fetch EAV Medical Profile
@@ -652,17 +659,24 @@ with tab_plate:
                 add_search = st.text_input("Search Exact Product Name (e.g. 'chicken', 'egg')")
                 if add_search:
                     bool_search = " ".join([f"+{w}" for w in add_search.split()])
+                    start_time = time.time()
                     cursor.execute("""
-                        SELECT c.code, MAX(c.product_name) as product_name
-                        FROM food_db.products_core c
+                        SELECT c.code, c.product_name
+                        FROM (
+                            SELECT code, MAX(product_name) as product_name
+                            FROM food_db.products_core
+                            WHERE MATCH(product_name, ingredients_text) AGAINST(%s IN BOOLEAN MODE)
+                            AND product_name IS NOT NULL AND product_name != '' AND product_name != 'None'
+                            GROUP BY code
+                            LIMIT 10
+                        ) c
                         JOIN food_db.products_macros m ON c.code = m.code
-                        WHERE MATCH(c.product_name, c.ingredients_text) AGAINST(%s IN BOOLEAN MODE)
-                        AND c.product_name IS NOT NULL AND c.product_name != '' AND c.product_name != 'None'
-                        AND m.proteins_100g IS NOT NULL AND m.fat_100g IS NOT NULL AND m.carbohydrates_100g IS NOT NULL
-                        GROUP BY c.code
-                        LIMIT 10
+                        WHERE m.proteins_100g IS NOT NULL AND m.fat_100g IS NOT NULL AND m.carbohydrates_100g IS NOT NULL
+                        GROUP BY c.code, c.product_name
                     """, (bool_search,))
                     search_res = cursor.fetchall()
+                    elapsed = time.time() - start_time
+                    st.caption(f"⏱️ Plate Search Executed in {elapsed:.3f} seconds")
                     if search_res:
                         options = {f"{r['product_name']} ({r['code']})": r for r in search_res}
                         selected_str = st.selectbox("Select Product", list(options.keys()))