Mysql
 sql >> база данни >  >> RDS >> Mysql

Оптимизиране на заявката (Индексиране, EXPLAIN) Mysql

Продължавам да забравям термина, тъй като ми се появява много рядко, но така или иначе, вашите индекси не могат да бъдат оптимизирани с помощта на MONTH() и YEAR(), тъй като те са функции върху основните данни. Прилагайки RANGE от дати, те могат. Така че можете да запазите своя месец/година, като например, ако нещо е създадено през януари 2021 г. и актуализирано през март 2021 г., но в допълнение, добавяйки "and c.date_created>=current_date И current_date <=c.date_updated" , МОЖЕТЕ да използвате индекса, ако в него има създадена дата (по-малко важно в този случай за датата на актуализиране. По същия начин за другата ви таблица.

Освен това, когато имате лявото присъединяване от таблицата "a" към таблицата "c", след което прилагането на where, е почти все едно се опитвате да форсирате присъединяването, но остава ляво присъединяване поради ИЛИ.

Бих преместил условието, базирано на "c", към лявото присъединяване, след което просто бих тествал за записа, намерен там, като NULL или не.

Въпреки че не е ясно (не беше изяснено, когато попитах), МИСЛЯ, че когато се създаде нов запис "А", системата може всъщност да постави датата на създаване както в датата на създаване, така и в датата на актуализиране. АКО ТОВА Е СЛУЧАЙ, тогава трябва само да потърсим/загрижим за последното актуализирано поле за дата с текущия месец/година на дейност. Това вече е ОСНОВНОТО изискване за клаузата where -- НЕЗАВИСИМО от основното условие ИЛИ към таблицата "C".

Освен това, тъй като month() и year() не са sargeable (Благодаря, Оли), правя предварителна заявка, за да получа началото на текущия месец и следващия месец, за да мога да създам

WHERE > beginning of this month and LESS than beginning of next month

Що се отнася до индексите, бих започнал да актуализирам до

loan_applications_tbl ( date_created, date_updated, loan_status, current_loan, ippis )
topup_or_reapplication_tbl ( ippis, status, current_loan, date_created, date_updated )

Последна заявка за опит.

SELECT 
        a.id, 
        a.user_unique_id, 
        a.loan_location, 
        a.ippis, 
        a.tel_no,
        a.organisation, 
        a.branch, 
        a.loan_agree, 
        a.loan_type, 
        a.appr, 
        a.sold, 
        a.loan_status, 
        a.top_up, 
        a.current_loan, 
        a.date_created, 
        a.date_updated, 
        c.loan_id, 
        c.user_unique_id tu_user_unique_id, 
        c.ippis tu_ippis, 
        c.top_up_approved,
        c.loan_type tu_loan_type, 
        c.dse, 
        c.status, 
        c.current_loan tu_current_loan,
        c.record_category, 
        c.date_created tu_date_created,
        c.date_updated tu_date_updated 
    FROM 
        -- this creates inline mySQL variables I can use for the WHERE condition
        -- by doing comma after with no explicit join, it is a single row
        -- and thus no Cartesian result, just @variables available now
        ( select 
                -- first truncating any TIME portion by casting to DATE()
                @myToday := date(curdate()),
                @howFarBack := date_sub( @myToday, interval 6 month ),
                -- now subtract day of month -1 to get first of THIS month
                @beginOfMonth := date_sub( @myToday, interval dayOfMonth( @myToday ) -1 day ),
                -- and now, add 1 month for beginning of next
                @beginNextMonth := date_add( @beginOfMonth, interval 1 month ) ) SqlVars,

        loan_applications_tbl a
    
            LEFT JOIN topup_or_reapplication_tbl c
                ON  a.ippis = c.ippis   
                AND c.current_loan='1'
                AND c.status IN ('pending', 'corrected', 'Rejected', 
                                'Processing', 'Captured', 'Reviewed', 'top up') 
                AND 
                (
                        (@beginOfMonth <= c.date_created 
                    AND c.date_created < @beginNextMonth)
        
                OR
                        (@beginOfMonth <= a.date_updated 
                    AND a.date_updated < @beginNextMonth )
                )

    WHERE
            -- forces only activity for the single month in question
            -- since the "a" table knows of any "updates" to the "C",
            -- its updated basis will keep overall restriction to any accounts

            -- updated within this month in question only
            -- testing specifically for created OR updated within the
            -- current month in question

        a.date_created >= @howFarBack
        AND
            (
                    (@beginOfMonth <= a.date_created 
                AND a.date_created < @beginNextMonth)
        
            OR
                    (@beginOfMonth <= a.date_updated 
                AND a.date_updated < @beginNextMonth )
            )
        
        -- and NOW we can easily apply the OR without requiring
        -- to run against the ENTIRE set of BOTH tables.
        AND (
                    c.ippis IS NOT NULL
                OR 
                    ( a.loan_status IN (  'pending', 'corrected', 'Rejected', 'Processing', 
                            'Captured', 'Reviewed', 'top up')
                    AND (   
                            a.current_loan = '1' 
                        OR  (   a.current_loan = '0' 
                            AND a.loan_status IN ('Approved', 'Closed')
                            )
                        )
                    )
            )

ЗАКРИВАЩИ КОМЕНТАРИ ЗА ЗАПИТВАНЕ

Промених заявката, а също и основния индекс на първата таблица, за да ВКЛЮЧИМ (първа позиция) датата на създаване на записа. Добавих и допълнителна променлива @howFarBack, за да бъде максималното време за връщане назад, което да обмислите за заем. Пропуснах преди 6 месеца. Бихте ли трябвало да вземете предвид дадена сметка, по-стара от 6 месеца, за заем? Или акаунтът "а" записва нещо, което може да се върне преди 10 години и искате да включите? Моето впечатление е, че това е нова дата за добавяне на ЗАЯВЛЕНИЕ ЗА ЗАЕМ. Ако е така, оставянето да се върне 6 месеца назад, преди да бъде одобрено, финализирано, анулирано, все пак би попречило да се преглеждат исторически данни за толкова месеца.

В клаузата WHERE добавих изрично добавяне за CREATED_DATE>=@howFarBack. Никога не би било възможно да бъде създаден дъщерен запис, да не говорим за актуализиран по всяко време преди първоначалната дата на добавяне. Това ще принуди само активността за текущия месец ИЛИ НАПРЕД да се класира.

Например:Създайте заем на 28 април. Така че, изпълнявайки заявката, началото на месеца е 1 април, но ПО-МАЛКО от 1 май (това позволява включване на 30 април в 23:59:59 ч.)

Сега влизаме в май и промяната на заема се извършва на 4 май. Намираме се в нов месец и @howFarBack все още позволява на по-стари приложения до декември 2020 г. ВЪЗМОЖНО да се квалифицират в сравнение с цялата таблица с приложения, които биха могли да се върнат до 2005 г., както знаем. Винаги оставате с най-актуалните данни и можете да промените @howFarBack достатъчно лесно като максимално време за връщане назад. Това трябва да помогне на нуждите ви от производителност.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да поправите грешка:MySQL изключване неочаквано на Xampp поради плъгин 'Aria'

  2. Laravel MySQL как да подредите резултатите в същия ред като в клаузата whereIn

  3. създайте jcomponents с помощта на база данни

  4. Искам да добавя 30 дни към реда за дата на mysql

  5. MySQL и JSON - трансформирайте масива в редове