thảo luận [Thảo luận] Bạn hỏi chúng tôi trả lời.

Thai-Tu-Shang

Senior Member
Chào các bác.

Chắc hẳn tất cả mọi người ở đây trong quá trình làm việc của mình đều gặp phải những bài toán khá khoai và hóc búa tới từ khách hàng.

Vậy giải pháp bạn đối mặt với nó là gì, bạn xử lý vấn đề đó ra sao và kinh nghiệm truyền lại là gì.

Hoặc cũng có thể bạn đang có một vấn đề mà chưa thể giải quyết :D

Mục đích tạo ra theard này nhằm chia sẻ nhiều hơn những bài toán và quan trọng hơn là tư duy giải quyết vấn đề trong ngành lập trình.

Mình xin chia sẻ trước bài toán mình gặp phải nhé:
Mình có một hệ thống gồm rất nhiều bảng để xuất ra báo cáo khác nhau ( tầm 4 bảng với số lượng row liên quan khác nhau )

Một ngày đẹp trời, khách hàng muốn tích hợp thêm một phần mềm báo cáo bên ngoài về doanh số bán hàng của họ theo ngày/tuần/tháng.

Hệ thống đó sẽ xuất ra 1 file excel và nhiệm vụ của bên mình là cuối tuần họ sẽ import vào trong hệ thống khoảng 200k row và chia đều vào trong 4 bảng.

Vậy giải pháp cho bên mình là gì nhỉ ?

Solution:

Bên mình thực hiện tạo một bảng tạm có lưu tất cả dữ liệu của file excel đẩy vào. Sau đó thực hiện việc swap nó thành các bảng nhỏ tương ứng với từng row trong 4 bảng. Ví dụ bảng A chứa giá trị của table 1, B của table 2..

Tiếp đó thực hiện xử lý merge 2 bảng với nhau dưới tầng DB.

Vậy là tầng server bên mình chỉ xử lý mỗi phần import excel thôi. Còn xử lý đẩy dữ liệu vào như thế nào thì do tầng DB làm. Nó khá nhanh hơn cách truyền thống là xử lý tất cả ở tầng server.

Các bro có giải pháp nào hay hơn với vấn đề mình đưa ra không thì cứ chia sẻ nhé :D
 
Làm thế logic merge bảng sẽ nằm hoàn toàn dưới DB, các bạn dự định unit test những logic này như thế nào? Nếu không unit test, logic đơn giản thì cũng thôi, chứ nếu sau này nó trở nên phức tạp thì lúc đấy mờ mắt fix bug.
 
Làm thế logic merge bảng sẽ nằm hoàn toàn dưới DB, các bạn dự định unit test những logic này như thế nào? Nếu không unit test, logic đơn giản thì cũng thôi, chứ nếu sau này nó trở nên phức tạp thì lúc đấy mờ mắt fix bug.

Bác có giải pháp gì khác không
 
Bác viết procedure ở dưới db tách table import thành các table nhỏ à. Sau đó insert record table nhỏ vào 4 table gốc à.

Đúng rồi, em tách nó thành các bảng nhỏ tương ứng với các bảng cần thiết. Sau đó merge vào các table gốc
 
Bác có giải pháp gì khác không
Mình sẽ để toàn bộ logic xử lý ở layer trên. Như bạn nói 200k records/tuần, 1 năm 52 tuần là 10M/1 year. Các bạn định lưu dữ liệu trong bao lâu? Mà đây mới chỉ là 1 khách hàng. Không sớm thì muộn sẽ phải partion data và thêm database server. Theo kinh nghiệm của mình với tình huống thế thì ko nên có bất kỳ logic gì ở dưới database cả, database chỉ thuần là nơi chứa data như Nosql. Không thế thì sau này mờ mắt profiler, test manual trên dữ liệu thật. Dù sao đây cũng chỉ là ý kiến cá nhân người ngoài bởi mình ko thể hiểu rõ bài toán bằng các bạn, nói để tham khảo thôi.
 
Rt7E8tX.png
API gateway và db luôn là bottleneck của một hệ thống. Phần application ta có thể dễ dàng scale theo chiều ngang để đáp ứng lượng sử dụng tăng dần một cách dễ dàng. Nhưng gateway và db thì không dễ như thế. Nên khi thiết kế hệ thống DB và api gateway luôn phải gọn nhẹ nhất. Thím đưa xử lý xuống db như vậy thì sau này dữ liệu nhiều lên. Số lượng khách hàng tăng lên hay hệ thống bự lên thì thím tính sao. Lúc đó ngồi đập đi xây lại chết mẹ luôn đấy ko đùa đâu
nmvIYHe.png
.
Bên mình thiết kế db gọn nhẹ tối đa có thể. Loại bỏ toàn bộ trigger, foreign key, procedure, ... Trong các bảng chỉ mỗi primary key thôi. Đưa toàn bộ logic lên phía application có thể. Như vậy khi scale trong tương lai sẽ dễ dàng hơn.
 
Mình sẽ để toàn bộ logic xử lý ở layer trên. Như bạn nói 200k records/tuần, 1 năm 52 tuần là 10M/1 year. Các bạn định lưu dữ liệu trong bao lâu? Mà đây mới chỉ là 1 khách hàng. Không sớm thì muộn sẽ phải partion data và thêm database server. Theo kinh nghiệm của mình với tình huống thế thì ko nên có bất kỳ logic gì ở dưới database cả, database chỉ thuần là nơi chứa data như Nosql. Không thế thì sau này mờ mắt profiler, test manual trên dữ liệu thật. Dù sao đây cũng chỉ là ý kiến cá nhân người ngoài bởi mình ko thể hiểu rõ bài toán bằng các bạn, nói để tham khảo thôi.



Rt7E8tX.png
API gateway và db luôn là bottleneck của một hệ thống. Phần application ta có thể dễ dàng scale theo chiều ngang để đáp ứng lượng sử dụng tăng dần một cách dễ dàng. Nhưng gateway và db thì không dễ như thế. Nên khi thiết kế hệ thống DB và api gateway luôn phải gọn nhẹ nhất. Thím đưa xử lý xuống db như vậy thì sau này dữ liệu nhiều lên. Số lượng khách hàng tăng lên hay hệ thống bự lên thì thím tính sao. Lúc đó ngồi đập đi xây lại chết mẹ luôn đấy ko đùa đâu
nmvIYHe.png
.
Bên mình thiết kế db gọn nhẹ tối đa có thể. Loại bỏ toàn bộ trigger, foreign key, procedure, ... Trong các bảng chỉ mỗi primary key thôi. Đưa toàn bộ logic lên phía application có thể. Như vậy khi scale trong tương lai sẽ dễ dàng hơn.


Bên nó đang tính tới trường hợp khi chạy tác vụ import mà hệ thống đang sử dụng thì nó sẽ chiếm toàn bộ tài nguyên server dẫn tới các thằng khác chết theo.

Giống hệ thống bên họ bây giờ khi import thì các tác vụ khác hầu như là xoay tròn hoặc đơ luôn, ko làm gì đc cả.
 
Bên nó đang tính tới trường hợp khi chạy tác vụ import mà hệ thống đang sử dụng thì nó sẽ chiếm toàn bộ tài nguyên server dẫn tới các thằng khác chết theo.

Giống hệ thống bên họ bây giờ khi import thì các tác vụ khác hầu như là xoay tròn hoặc đơ luôn, ko làm gì đc cả.
Nếu vậy thì phải đề xuất mua thêm server mà xử lý, chứ xác suất DB phình to nhanh mà để logic dưới DB thì sau mệt lắm. Nhất là cái việc merge data là cái task rất chán, vì nhiều lúc ngay bản thân data đưa vào nó ko chuẩn theo document bọn nó đưa đâu. Bởi vậy nên ưu tiên chuyện dễ test/debug, insert update delete trước hiệu năng. MS SQL mà mình dùng y chang không khác NoSQL, rất buồn cười
 
Mấy thím cho e hỏi Mysql không có returning sau khi insert giống như PostgreSQL có cách nào lấy data mình vừa insert vào ko nhỉ ?
 
Giờ insert số lượng 10 record thì không lấy được đúng ko thím
Nếu xài InnoDB với innodb_autoinc_lock_mode thì kết hợp với ROW_COUNT() nhé: LAST_INSERT_ID() là thằng đầu tiên, LAST_INSERT_ID()+ROW_COUNT()-1 là thằng cuối cùng.
 
Last edited:
Nếu xài InnoDB với innodb_autoinc_lock_mode thì kết hợp với ROW_COUNT() nhé: LAST_INSERT_ID() là thằng đầu tiên, ROW_COUNT()-1 là thằng cuối cùng.
Cái thằng LAST_INSERT_ID() có khi nào bị khai ko thím, lỡ như 2 thằng insert 1 lúc thì nó trả về có đúng ID mình vừa insert ko nhỉ :adore:
 
Cái thằng LAST_INSERT_ID() có khi nào bị khai ko thím, lỡ như 2 thằng insert 1 lúc thì nó trả về có đúng ID mình vừa insert ko nhỉ :adore:
LAST_INSERT_ID() dựa vào connection 2 thằng cùng ghi thuộc 2 connection khác nhau sẽ nhận kết quả khác nhau.
 
Nếu liên quan tới báo cáo, hay dùng để phân tích dữ liệu
thì best practice là thêm 1 con read replicate từ con db chính.
Rồi code con báo cáo đọc vào con read replicate thôi, lúc đó muốn đẩy logic vào xử lý ở tầng db, hay ở tầng code application thì cũng ko phải lo lắng sợ ảnh hưởng tới con db master
 
Nếu xài InnoDB với innodb_autoinc_lock_mode thì kết hợp với ROW_COUNT() nhé: LAST_INSERT_ID() là thằng đầu tiên, LAST_INSERT_ID()+ROW_COUNT()-1 là thằng cuối cùng.
mysql mỗi cái storage engine đúng là không khác gì một cái database riêng, feature sets khác hẳn =)
cơ mà làm tôi lại nhớ đến mấy cậu cv nói thành thạo mysql nhưng hỏi myisam innodb là gì liền tắc tịt :v
 
Back
Top