Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Tối ưu hóa truy vấn (Lập chỉ mục, GIẢI THÍCH) Mysql

Tôi tiếp tục quên thuật ngữ này vì nó rất hiếm khi xuất hiện đối với tôi, nhưng dù sao, các chỉ mục của bạn không thể được tối ưu hóa bằng cách sử dụng MONTH () và YEAR () vì chúng là các hàm trên dữ liệu cơ bản. Bằng cách áp dụng một RANGE ngày, họ có thể. Vì vậy, bạn có thể giữ lại tháng / năm của mình, chẳng hạn như nếu nội dung nào đó được tạo vào tháng 1 năm 2021 và cập nhật vào tháng 3 năm 2021, nhưng thêm vào đó, thêm "và c.date_create> =current_date VÀ current_date <=c.date_updated" , bạn CÓ THỂ sử dụng chỉ mục nếu nó có ngày được tạo trong đó (ít quan trọng hơn trong trường hợp này là ngày được cập nhật. Tương tự với bảng khác của bạn.

Ngoài ra, khi bạn có phép tham gia bên trái từ bảng "a" đến bảng "c", sau đó áp dụng ở đâu, điều đó gần giống như bạn đang cố gắng buộc tham gia nhưng vẫn tham gia bên trái do HOẶC.

Tôi sẽ chuyển điều kiện dựa trên "c" sang kết hợp bên trái, sau đó chỉ cần kiểm tra bản ghi được tìm thấy ở đó là NULL hay không.

Mặc dù không rõ ràng (không được làm rõ khi tôi hỏi), tôi NGHĨ rằng khi một bản ghi "A" mới được tạo, hệ thống có thể thực sự đặt ngày tạo vào cả ngày được tạo và ngày được cập nhật. NẾU ĐÂY LÀ TRƯỜNG HỢP, thì chúng tôi chỉ cần truy vấn / quan tâm đến trường ngày cập nhật lần cuối với tháng / năm hoạt động hiện tại. Đó hiện là yêu cầu CHÍNH đối với mệnh đề where - REGARDLESS của điều kiện OR cơ bản đối với bảng "C".

Ngoài ra, vì tháng () và năm () không có thể phân tích (Cảm ơn Ollie), tôi đang thực hiện truy vấn trước để có được đầu tháng hiện tại và tháng sau để tôi có thể xây dựng

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

Đối với các chỉ mục, tôi sẽ bắt đầu cập nhật lên

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

Truy vấn cuối cùng để thử.

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

ĐÓNG NHẬN XÉT CHO QUERY

Tôi đã sửa đổi truy vấn và cả chỉ mục chính trên bảng đầu tiên thành BAO GỒM (vị trí đầu tiên) ngày tạo bản ghi. Tôi cũng đã thêm một biến bổ sung @howFarBack để trở thành thời gian quay lại tối đa để xem xét khoản vay. Tôi đã mặc định trở lại 6 tháng. Bạn có bao giờ cần xem xét một tài khoản nhất định cũ hơn 6 tháng để vay không? Hay tài khoản "a" ghi lại thứ gì đó có thể quay trở lại 10 năm và muốn đưa vào? Ấn tượng của tôi đó là ngày thêm ĐƠN VAY VỐN mới. Nếu vậy, việc cho phép lùi lại 6 tháng trước khi được phê duyệt, hoàn thiện, hủy bỏ sẽ vẫn ngăn cản việc trải qua nhiều tháng dữ liệu trong lịch sử.

Trong mệnh đề WHERE, tôi đã thêm phép bổ sung rõ ràng cho CREATED_DATE> =@howFarBack. Sẽ không bao giờ có thể tạo một bản ghi con, chứ chưa nói đến việc cập nhật bất kỳ lúc nào trước ngày thêm ban đầu. Điều này sẽ buộc chỉ hoạt động của tháng hiện tại HOẶC TIẾN HÀNH mới đủ điều kiện.

Ví dụ:Tạo một khoản vay vào ngày 28 tháng 4. Vì vậy, khi chạy truy vấn, đầu tháng là ngày 1 tháng 4 nhưng ÍT hơn ngày 1 tháng 5 (điều này cho phép bao gồm ngày 30 tháng 4 lúc 11:59:59 tối)

Bây giờ, chúng tôi bước vào tháng 5 và một thay đổi về khoản vay sẽ được thực hiện vào ngày 4 tháng 5. Chúng tôi đang ở trong một tháng mới và @howFarBack vẫn cho phép các ứng dụng cũ hơn cho đến tháng 12 năm 2020 để CÓ THỂ đủ điều kiện so với toàn bộ bảng ứng dụng có thể quay trở lại từ năm 2005 cho tất cả những gì chúng tôi biết. Bạn luôn cập nhật dữ liệu mới nhất và bạn có thể thay đổi @howFarBack dễ dàng, đủ để coi là thời gian quay lại tối đa. Điều này sẽ giúp ích cho nhu cầu hiệu suất của bạn.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chọn, nơi chứa Mảng JSON

  2. Hợp nhất hai cột, nhiều hàng bỏ qua các bản sao - MySQL

  3. MySQL:Cập nhật tất cả các hàng đặt trường thành 0, nhưng đặt trường của một hàng thành 1

  4. Ứng dụng web PHP:câu hỏi thực tiễn tốt nhất về thiết kế cơ sở dữ liệu mysql

  5. Thông báo ClusterControl 1.4.1 - Phiên bản ProxySQL