sql >> Database >  >> RDS >> Mysql

Zoekopdracht optimaliseren (Indexeren, UITLEG) Mysql

Ik vergeet de term steeds, omdat het zelden in me opkomt, maar hoe dan ook, je indexen kunnen niet worden geoptimaliseerd door MONTH() en YEAR() te gebruiken, omdat het functies zijn op de onderliggende gegevens. Door een datumbereik toe te passen, kunnen ze. U kunt dus uw maand/jaar behouden alsof er iets is gemaakt in jan. 2021 en bijgewerkt in maart 2021, maar daarnaast een "and c.date_created>=current_date AND current_date <=c.date_updated" , kunt u de index gebruiken als deze de aanmaakdatum bevat (in dit geval minder belangrijk voor de bijgewerkte datum. Hetzelfde geldt voor uw andere tabel.

Bovendien, als je je linker-join hebt van de "a" naar de "c"-tabel, en dan toepast waar, is het bijna alsof je de join probeert te forceren maar links-join blijft vanwege de OF.

Ik zou de op "c" gebaseerde voorwaarde naar de linker-join verplaatsen, en dan gewoon testen op het record dat daar wordt gevonden als NULL of niet.

Hoewel niet duidelijk (werd niet verduidelijkt toen ik ernaar vroeg), DENK ik dat wanneer een nieuw "A"-record wordt gemaakt, het systeem de aanmaakdatum in zowel de aanmaakdatum als de bijgewerkte datum kan zetten. ALS DIT HET GEVAL IS, dan hoeven we alleen het laatst bijgewerkte datumveld te bevragen/betreffen met de huidige maand/jaar van activiteit. Dat is nu de PRIMAIRE vereiste voor de waar-clausule -- ONGEACHT de onderliggende OF-voorwaarde voor de "C"-tabel.

Bovendien zijn de maand() en jaar() niet sargeable (Bedankt Ollie), ik doe een prequery om het begin van de huidige maand en volgende maand te krijgen, zodat ik een

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

Wat indexen betreft, zou ik beginnen met updaten naar

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

Laatste vraag om mee te proberen.

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')
                            )
                        )
                    )
            )

SLOTOPMERKINGEN VOOR QUERY

Ik heb de query en ook de primaire index op de eerste tabel gewijzigd om de datum van het record op te nemen (eerste positie). Ik heb ook een extra variabele toegevoegd @howFarBack om de maximale terugverdientijd te zijn die moet worden overwogen voor een lening. Ik was standaard 6 maanden terug. Zou u ooit een bepaalde rekening ouder dan 6 maanden moeten overwegen voor een lening? Of is de "a"-account iets dat 10 jaar terug kan gaan en wil opnemen? Mijn indruk is dat het een nieuwe toevoegingsdatum voor LENING is. Als dat zo is, zou het toestaan ​​om zes maanden terug te gaan voordat het is goedgekeurd, definitief of geannuleerd, nog steeds voorkomen dat er in het verleden evenveel maanden aan gegevens worden verwerkt.

In de WHERE-clausule heb ik expliciete toevoeging toegevoegd voor de CREATED_DATE>=@howFarBack. Het zou nooit mogelijk zijn om een ​​kindrecord aan te maken, laat staan ​​dat het op enig moment vóór de oorspronkelijke toevoegingsdatum wordt bijgewerkt. Dit dwingt alleen de activiteit van de huidige maand OF VOORUIT om zich te kwalificeren.

Bijvoorbeeld:maak een lening aan op 28 april. Dus als we de zoekopdracht uitvoeren, is het begin van de maand 1 april, maar MINDER dan 1 mei (hierdoor kan 30 april om 23:59:59 uur worden opgenomen)

Nu komen we in mei en op 4 mei wordt de lening gewijzigd. We bevinden ons in een nieuwe maand en de @howFarBack staat nog steeds toe dat oudere applicaties tot december 2020 MOGELIJK in aanmerking komen versus de hele tabel met applicaties die voor zover we weten terug kunnen gaan tot 2005. U blijft altijd bij de meest actuele gegevens en u kunt de @howFarBack eenvoudig genoeg wijzigen als de maximale teruggaande tijd. Dit zou moeten helpen bij uw prestatiebehoeften.




  1. Werken met hulpmiddelen op het scherm in Access 2019

  2. Functies versus procedures in Oracle

  3. Hoe records willekeurig uit de Oracle-database te halen?

  4. Oracle-database vergrendelen voordat u de scripts voor het verwijderen/laden van gegevens uitvoert