Performance issue khi tạo Billing Credit Memo bằng VF01 trong SAP — Kinh nghiệm thực tế xử lý bottleneck

1️⃣ Bối cảnh vấn đề

Trong quá trình vận hành hệ thống SAP, team mình gặp phải vấn đề nghiêm trọng về performance khi user thực hiện tạo billing type là Credit Memo bằng transaction VF01. Khi user tạo Credit Memo, hệ thống tiêu tốn gần như toàn bộ process update, khiến các transaction khác không còn đủ tài nguyên để thực hiện cập nhật dữ liệu.

Process update bị treo khi user tạo billing Credit Memo bằng VF01
Hình 1: Process update bị treo khi user tạo billing Credit Memo bằng VF01

Nguyên nhân:

Điều tra log và code cho thấy trong EXIT_SAPLVEDF_002 (include ZXEDFU02), hệ thống có logic tạo output IDoc hóa đơn. Riêng với Credit Memo, đoạn code này thực hiện INNER JOIN giữa hai bảng lớn:

  • VBRK (3656489 entries)

  • VBRP (44817288 entries)

Việc INNER JOIN trên PRD với volume dữ liệu lớn như vậy khiến truy vấn bị chậm, kéo theo việc tạo Credit Memo mất nhiều thời gian, và khiến các process cập nhật bị treo.

Logic ban đầu join trực tiếp VBRK và VBRP
Hình 2: Logic ban đầu join trực tiếp VBRK và VBRP

2️⃣ Giải pháp ban đầu của vendor

Vendor đã review toàn bộ code trong user exit và sửa lại câu lệnh SQL để tránh dùng INNER JOIN trực tiếp. Giải pháp tạm thời:

  • Tách truy vấn JOIN thành nhiều truy vấn đơn lẻ:
    1. Lấy số Sales Order (SO) gốc qua bảng VBAP
    2. Lấy số billing gốc từ VBRP
    3. Lấy số VAT gốc từ VBRK

Tuy nhiên, cách tách này chỉ cải thiện tốc độ ~3.8 lần vì phần 2 (lấy billing gốc từ VBRP không theo key chính) vẫn scan dữ liệu lớn, chưa thực sự tối ưu.

Logic vendor lấy dữ liệu từ ba bảng VPAP, VBRP, VBRK
Hình 3: Logic vendor lấy dữ liệu từ ba bảng VPAP, VBRP, VBRK

3️⃣ Giải pháp tối ưu triệt để

Dựa trên kinh nghiệm xử lý SQL và hiểu rõ quan hệ giữa các bảng (VBFA, VBRK, VBRP), mình đã thiết kế lại truy vấn:

  • Không JOIN trực tiếp hai bảng lớn
  • Tận dụng primary keyforeign key chuẩn của SAP
  • Bổ sung logic để lấy thêm SO item của SO gốc, đảm bảo dữ liệu đầy đủ và đúng nghiệp vụ.

Cách mình làm:

1. Lấy số Sales Order (SO) gốc qua bảng VBAP => giữ nguyên logic nhưng lấy thêm SO item gốc

2. Lấy số billing gốc từ VBRP  => lấy từ bảng VBFA dựa vào SO & SO item và là key chính

3. Lấy số VAT gốc từ VBRK => giữ nguyên

Nhờ đó, toàn bộ quá trình lấy dữ liệu gần như tức thì, không còn bottleneck.

Hình 4: Giải pháp của mình lấy dữ liệu từ VBAP, VBFA, VBRK
Hình 4: Giải pháp của mình lấy dữ liệu từ VBAP, VBFA, VBRK

4️⃣ Kết quả so sánh

Giai đoạnTổng thời gian (Microseconds)Thời gian (Minutes)
Before297,094,4104.95 phút
After 1 (Vendor)78,196,8511.30 phút (~3.8x nhanh hơn)
After 2 (Tối ưu triệt để)Gần như ngay lập tứcGần như bằng 0

5️⃣ Bài học kinh nghiệm

  • Hiểu rõ nghiệp vụ & data structure: là điều tiên quyết khi tối ưu SQL trong SAP.
  • Hạn chế JOIN trực tiếp các bảng lớn, đặc biệt khi dữ liệu tăng trưởng liên tục.
  • Tinh thần học hỏi và thử nghiệm sẽ giúp bạn giải quyết được các bottleneck khó nhằn nhất.


🎯Kết luận

Việc xử lý thành công issue này là minh chứng rằng chỉ cần hiểu đúng dữ liệu và logic nghiệp vụ, bạn hoàn toàn có thể tối ưu hệ thống SAP một cách hiệu quả mà không phụ thuộc hoàn toàn vào vendor.

Mình tự hào khi đã đóng góp giải pháp thực tế, giúp hệ thống vận hành ổn định hơn.
Mong rằng chia sẻ này sẽ hữu ích cho các bạn đang làm SAP ABAP, Basis, hay tư vấn module có liên quan đến billing & output IDoc.

Bạn đã từng gặp tình huống tương tự? Chia sẻ thêm kinh nghiệm tối ưu SAP của bạn nhé!

Post a Comment

0 Comments