Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Optimalkan kueri (Pengindeksan, JELASKAN) Mysql

Saya terus melupakan istilah itu karena istilah itu sangat jarang muncul bagi saya, tetapi bagaimanapun, indeks Anda tidak dapat dioptimalkan dengan menggunakan MONTH() dan YEAR() karena keduanya berfungsi pada data yang mendasarinya. Dengan menerapkan RANGE tanggal, mereka bisa. Jadi Anda dapat menyimpan bulan/tahun Anda seperti jika ada sesuatu yang dibuat pada Jan 2021 dan diperbarui pada Mar 2021, tetapi selain itu, menambahkan "and c.date_created >= current_date AND current_date <= c.date_updated" , Anda BISA menggunakan indeks jika memiliki tanggal pembuatan di dalamnya (kurang penting dalam hal ini untuk tanggal yang diperbarui. Demikian pula untuk tabel Anda yang lain.

Selain itu, ketika Anda memiliki gabungan kiri dari tabel "a" ke "c", lalu menerapkan di mana, hampir seperti Anda mencoba memaksa gabungan tetapi tetap bergabung dengan kiri karena OR.

Saya akan memindahkan kondisi berbasis "c" ke gabungan kiri, lalu hanya menguji catatan yang ditemukan di sana sebagai NULL atau tidak.

Meskipun tidak jelas (tidak diklarifikasi ketika saya bertanya), saya BERPIKIR bahwa ketika catatan "A" baru dibuat, sistem sebenarnya dapat memasukkan tanggal pembuatan ke dalam tanggal dibuat dan tanggal diperbarui. JIKA INI KASUSNYA, maka kita hanya perlu menanyakan/memperhatikan bidang tanggal terakhir yang diperbarui dengan bulan/tahun aktivitas saat ini. Itu sekarang persyaratan UTAMA untuk klausa where -- TERLEPAS dari kondisi OR yang mendasari ke tabel "C".

Selain itu, karena bulan() dan tahun() tidak sargeable (Terima kasih Ollie), saya sedang melakukan prequery untuk mendapatkan awal bulan ini dan bulan depan sehingga saya dapat membuat

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

Untuk indeks, saya akan mulai memperbarui ke

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

Permintaan terakhir untuk dicoba.

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

KOMENTAR PENUTUP UNTUK QUERY

Saya memodifikasi kueri dan juga indeks utama pada tabel pertama menjadi TERMASUK (posisi pertama) tanggal pembuatan catatan. Saya juga menambahkan variabel tambahan @howFarBack sebagai waktu mundur maksimum untuk dipertimbangkan untuk pinjaman. Saya default ke 6 bulan yang lalu. Apakah Anda perlu mempertimbangkan akun yang diberikan lebih dari 6 bulan untuk pinjaman? Atau apakah akun "a" mencatat sesuatu yang bisa kembali 10 tahun dan ingin disertakan? Kesan saya adalah tanggal penambahan APLIKASI PINJAMAN baru. Jika demikian, membiarkan 6 bulan ke belakang sebelum disetujui, diselesaikan, dibatalkan akan tetap mencegah data selama berbulan-bulan secara historis.

Dalam klausa WHERE, saya menambahkan penambahan eksplisit untuk CREATED_DATE>=@howFarBack. Catatan anak tidak akan pernah mungkin dibuat, apalagi diperbarui kapan saja sebelum tanggal penambahan asli. Ini akan memaksa hanya aktivitas bulan ini ATAU MAJU yang memenuhi syarat.

Contoh:Buat pinjaman pada tanggal 28 April. Jadi menjalankan kueri, awal bulan adalah 1 April tetapi KURANG dari 1 Mei (ini memungkinkan penyertaan 30 April pukul 11:59:59 malam)

Sekarang, kita masuk ke Mei dan perubahan pinjaman dilakukan pada 4 Mei. Kami berada di bulan baru dan @howFarBack masih memungkinkan aplikasi lama sejauh Desember 2020 untuk MUNGKIN memenuhi syarat vs seluruh tabel aplikasi yang bisa kembali sejauh 2005 untuk semua yang kita tahu. Anda selalu tetap dengan data terbaru dan Anda dapat mengubah @howFarBack dengan cukup mudah sebagai waktu mundur maksimum. Ini akan membantu kebutuhan kinerja Anda.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bergabunglah dengan tabel dari dua server yang berbeda

  2. mysql recursive(tree) parent child kategori

  3. Bagaimana cara mengubah tabel MySQL ke UTF-8?

  4. Pelacakan waktu nyata di peta google

  5. Bagaimana cara menghitung kemunculan di kolom yang dipisahkan koma?