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

truy vấn tốn kém làm hỏng máy chủ cơ sở dữ liệu - đang tìm cách giảm thiểu

Rất tiếc, tôi có thể thử viết truy vấn của bạn theo những dòng sau:

SELECT Sale_Item.deleted, Sale_Item.deleted_by,
       Sale_Item.sale_time, Sale_Item.sale_date,
       Sale_Item.comment,
       Sale_Item.payment_type,
       Sale_Item.customer_id,
       Sale_Item.employee_id,
       Sale_Item.category,
       Sale_Item.sale_id, Sale_Item.item_id, NULL as item_kit_id, Sale_Item.line, 
       Sale_Item.supplier_id,
       Sale_Item.serialnumber, Sale_Item.description,
       Sale_Item.quantity_purchased, Sale_Item.item_cost_price, Sale_Item.item_unit_price,
       Sale_Item.discount_percent,
       Sale_Item.lineSubtotal,
       Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + (Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + Sale_Item.non_cumulative) * COALESCE(Tax.cumulative, 0) AS lineTax,
       Sale_Item.lineSubtotal + (Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + (Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + Sale_Item.non_cumulative) * COALESCE(Tax.cumulative, 0)) AS lineTotal,
       Sale_Item.lineSubtotal - (Sale_Item.item_cost_price * Sale_Item.quantity_purchased) AS profit

FROM (SELECT Sale.deleted, Sale.deleted_by,
             Sale.sale_time, DATE(Sale.sale_time) AS sale_date,
             Sale.comment,
             Sale.payment_type,
             Sale.customer_id,
             Sale.employee_id,
             Item.category,
             Sale_Item.sale_id, Sale_Item.item_id, NULL as item_kit_id, Sale_Item.line, 
             Sale_Item.supplier_id,
             Sale_Item.serialnumber, Sale_Item.description,
             Sale_Item.quantity_purchased, Sale_Item.item_cost_price, Sale_Item.item_unit_price,
             Sale_Item.discount_percent,
             (Sale_Item.item_unit_price * Sale_Item.quantity_purchased) - (Sale_Item.item_unit_price * Sale_Item.quantity_purchased * Sale_Item.discount_percent / 100) as lineSubtotal                 
      FROM phppos_sales_items Sale_Item
      JOIN phppos_sales Sale
        ON Sale.sale_id = Sale_Item.sale_id
           AND Sale.sale_time >= TIMESTAMP('2014-04-01')
           AND Sale.sale_time < TIMESTAMPADD(MONTH, 1, '2014-04-01')
           AND Sale.location_id = 1
           AND Sale.store_account_payment = 0) Sale_Item

LEFT JOIN (SELECT Tax.sale_id, Tax.item_id, Tax.line,
                  SUM(CASE WHEN Tax.cumulative = 1 THEN Tax.percent ELSE 0 END) as cumulative,
                  SUM(CASE WHEN Tax.cumulative <> 1 THEN Tax.percent ELSE 0 END) as non_cumulative
           FROM phppos_sales_item_taxes Tax
           JOIN phppos_sales Sale
             ON Sale.sale_id = Tax.sale_id
                AND Sale.sale_time >= TIMESTAMP('2014-04-01')
                AND Sale.sale_time < TIMESTAMPADD(MONTH, 1, '2014-04-01')
                AND Sale.location_id = 1
                AND Sale.store_account_payment = 0
           GROUP BY Tax.sale_id, Tax.item_id, Tax.line) Tax
       ON Tax.sale_id = Sale_Item.sale_id
          AND Tax.item_id = Sale_Item.sale_id
          AND Tax.line =Sale_Item.line 

Đã di chuyển một số cột cho mục đích tổ chức. Điều này sẽ không ảnh hưởng lớn đến thời gian xử lý.

Tôi đã xóa tham chiếu đến phppos_suppliers như:

  1. Bạn không sử dụng bất kỳ cột nào từ bảng
  2. Đó là LEFT JOIN , nghĩa là bạn không yêu cầu hàng tồn tại ở đó.

Tôi đã di chuyển GROUP BY vào một truy vấn con mới, bởi vì phppos_sales_item_taxes là bảng duy nhất có thể có các hàng trùng lặp cho các tiêu chí đã cho. Tôi đã bao gồm tham chiếu đến phppos_sales bởi vì tôi không chắc liệu trình tối ưu hóa của MySQL (hoặc bất kỳ, thực sự) có đủ thông minh để đẩy citeria xuống hay không.

Phần chính của truy vấn đã được chuyển đến một truy vấn con đơn giản nên tôi không cần phải nhập công thức cho lineSubtotal nhiều lần. Tôi đã sử dụng các công thức tương tự trong suốt, nhưng có các phiên bản đơn giản hóa có sẵn:

Sale_Item.item_unit_price * Sale_Item.quantity_purchased * (1 - (Sale_Item.discount_percent / 100)) as lineSubtotal  

Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative + Tax.cumulative + Tax.non_cumulative * Tax.cumulative, 0) as Tax

.... bạn có thể phải chạy những điều này bằng kế toán, vì chúng có xu hướng (dễ hiểu) về thứ tự hoạt động. Điều này có thể dẫn đến thời gian chạy nhanh hơn nhưng tôi nghi ngờ điều đó; chủ yếu đây là về việc đơn giản hóa các thuật ngữ để dễ đọc hơn.

Bạn đã không cung cấp bất kỳ bố cục bảng nào cho nửa còn lại của truy vấn, nhưng tôi cho rằng nó tương tự. Việc sửa đổi liên quan được để lại như một bài tập cho người đọc.

Các chiến lược giảm thiểu chung

Ngoài bất kỳ khả năng tăng tốc độ thay đổi truy vấn nào có thể có, có một số điều bạn có thể làm để khắc phục sự cố:

  1. Trong lớp ứng dụng của bạn, buộc truy vấn này (và có thể cả những truy vấn khác) phải trải qua một quy trình gửi công việc mà kết quả của nó có thể được truy xuất sau đó. Không thể chạy bản sao mới của truy vấn này cho đến khi bản sao trước đó hoàn thành. Tôi giả sử php có một thư viện hiện có cho việc này. Nói chung, chỉ cần điều chỉnh quá trình gửi có thể là tất cả những gì bạn cần.
  2. Dữ liệu đang được truy xuất dường như có thể lưu vào bộ nhớ đệm - lưu trữ mọi thứ trước sale_date được xử lý gần đây nhất và sau đó chỉ nhận được thông tin mới khi đang di chuyển (mặc dù quá trình chuyển đổi không thực sự khác biệt như vậy từ bản gốc - tuy nhiên, chỉ đơn giản là không thực hiện thêm các phép nối có thể hữu ích).
  3. Không cho phép các truy vấn trong khoảng thời gian xử lý hiện tại. Điều này sẽ ngăn hệ thống cố gắng truy cập vào các hàng chưa được cam kết và có khả năng tránh xa các trang lập chỉ mục đang được sửa đổi. Loại thủ thuật này hoạt động hiệu quả nhất nếu bộ nhớ của bạn được bố trí để tận dụng lợi thế của I / O đồng thời.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Danh sách thả xuống được phổ biến động PHP MySQL

  2. Lỗi MySQL # 2014 - Các lệnh không đồng bộ; bạn không thể chạy lệnh này bây giờ

  3. Không có thực thể ORM của Doctrine được ánh xạ theo cấu hình hiện tại

  4. Máy chủ MySQL đã biến mất với Ruby on Rails

  5. Lỗi MySQL 2013