General pit custom function of relational database

Custom functions, like scalar subqueries, when the result set (row number N) returned by the main query is huge, the query in the custom function will be accessed N times

The only applicable scenario of user-defined function is paging query. Other scenarios basically have potential risks and need to be rewritten.

SELECT rrs.o_id,
       (SELECT min(IFNULL(get_product_minOrderPkgQty(rrs.o_id, rct.typeId) *
                          get_product_sale_quantity(rrs.o_id, rct.typeId),
                          999999))
          FROM ruigu_customer_type AS rct
         WHERE rct.typeId > 40
           AND rct.current_using = 1) AS min_num
  FROM ruigu_replace_sku AS rrs

The above is a mysql statement. The execution time is 20s. SQL involves two tables and two custom functions

According to the optimization experience of ORACLE in the past, user-defined functions may be the bottleneck of SQL statements. The definition of functions is as follows:

--1
CREATE DEFINER=`dev_team3`@`%` FUNCTION `get_product_minOrderPkgQty`(product_id int, customer_type int) RETURNS int(11)
begin
  declare minOrderPkgQty_result int(11);
    select minOrderPkgQty into minOrderPkgQty_result 
    from `ruigu_product_sale_configuration`
    where productId=product_id and customerTypeId=customer_type limit 1;
  return minOrderPkgQty_result;
--2
CREATE DEFINER=`dev_team3`@`%` FUNCTION `get_product_sale_quantity`(product_id int, customer_type int) RETURNS int(11)
begin
  declare quantity_result int(11);
    select saleQuantity into quantity_result 
    from `ruigu_product_sale_configuration`
    where productId=product_id and customerTypeId=customer_type limit 1;
  return quantity_result;

Whether or not a custom function causes performance problems depends on the number of rows returned by the main query, that is

SELECT count(*)
    FROM ruigu_customer_type AS rct
   WHERE rct.typeId > 40
     AND rct.current_using = 1

Because there is no common sense measurement value for mysql, ORACLE is 10000 rows (the attenuation range of 20w rows of disks with good IO performance can also be accepted)

Therefore, you can only use other methods to "try": when you encounter SQL such as custom functions and scalar subqueries, you can determine whether they have performance problems

If the user-defined function and scalar subquery comments are dropped, the original SQL will be run. If the efficiency is improved, it will be rewritten~

primary SQL After the user-defined function is removed, the performance is significantly improved, so it is rewritten as follows:
select w.o_id,
       min(IFNULL(w.quantity_result * w.minOrderPkgQty_result, 999999))
  from (select c.saleQuantity   as quantity_result,
               c.minOrderPkgQty as minOrderPkgQty_result,
               a.o_id
          from ruigu_replace_sku a
         inner join (select typeId
                      from ruigu_customer_type rct
                     WHERE rct.typeId > 40
                       AND rct.current_using = 1) b
          left join ruigu_product_sale_configuration c
            on a.o_id = c.productId
           and b.typeId = c.customerTypeId) w
 group by w.o_id;

//After rewriting, SQL runs for 300ms

 

 

 

Keywords: SQL MySQL Oracle

Added by Gordonator on Tue, 07 Jan 2020 15:03:43 +0200