Tôi chém gió chứ có phải bảo vệ luận văn đâu mà anh kêu tôi đưa luận điểm với bench test. Mấy anh làm quá.Tôi chửi việc anh đưa luận điểm không đủ chặt chẽ.
Tôi có nói gì về nosql đâu nhỉ? Tôi chỉ nói nhiều khi do politics trong công ty chef mới lên muốn có nguồn gió mới đổi sql thành nosql mặc dù sql nó chả có vấn đề gì thì sao lại chửi tôi nhỉ? Hay anh chửi lộn tôi với ai thế.À chửi thêm cái nosql nữa.
Anh @lam vung lau lam đã out topic rồi làm tôi không được học thêm cái gì mới.
Bàn về con người.
Ở trên các bạn nói abstract thinking hay abstraction thì đúng chuyên môn và hàn lâm quá rồi. Tôi thì chỉ có một cái giải thích thôi đó là vì tôi lười. Tôi lười phải chạy theo các thay đổi của tụi bên Business và cả theo chef tổng nên tôi phải làm sao mà khi có những thay đổi diễn ra, tôi phải không bị stress khi sửa các thay đổi đó vào.
Sẽ có những thời khắc mà các quyết định nó hoàn toàn mang tính "chính trị" chứ chẳng phải gì về công nghệ cái con mịa gì cả. Ví dụ đang local chạy tốt việc gì phải lên cloud, đang SQL tốt việc gì phải qua NoSQL. Đó là vì nỗi sợ của những người không hiểu. Họ sợ bị tụt hậu, họ sợ bị bỏ lỡ. Mà những người đó toàn là CEO, Chủ tịch quản trị, CIO thôi, toàn dân Politics cả chứ nền tảng technical được bao nhiêu so với dân chuyên môn. Nhưng đó là cách thế giới vận hành và phát triển.
Bàn về tech.
1.
Giờ ai nói và về select field nhanh hơn với select star thì thôi mấy anh tự làm cái test đi. Mấy anh lựa cái bảng nào nhiều dòng nhất mà mấy anh có làm cái SQL "Select * from table where id =" với cái "Select id from table where id=" xem coi nó lệch bao nhiêu ms. Đấy là phần SQL.
Rồi về phần mapping giờ mấy anh tự code một cái function map giữa 2 object A và B (copy giá trị 1-1). Một cái map full 20 properties một cái map 1 property. Rồi mấy anh đo xem coi nó lệch bao nhiêu ms.
Sau khi làm xong mấy anh báo lại xem mấy anh tối ưu được bao nhiêu ms.
Tôi báo kết quả luôn là 0ms. Tức là về performance các anh lợi được là 0ms.
Nhưng cũng phải nói các anh tiết kiệm được vài kb bộ nhớ trong quá trình map đấy.
Rồi giờ các anh đứng trước quyết định là mấy anh làm spaghetti code để tiết kiệm vài kb bộ nhớ trong vài giây thì có đáng không?
2. Rồi thứ 2 là về Raw SQL.
- Các anh nói các anh thích viết raw sql. It's ok. Đó là sở thích của các anh. Nhưng đứng ở vị trí của tôi trước dự án 20-30 dev. Các anh kêu tôi dùng raw sql á? Một là các anh bị điên. Hai là các anh bị khùng. Ai sẽ quản lý nổi cái đống raw sql đó? Convention, SQL Function, SQL Injection... ai sẽ validate? Rồi khi thay đổi Business Logic dùng cột A thay cột B thì ai sẽ ngồi search và replace rồi test lại là mọi thứ đều đúng?
- Rồi các anh gào lên là cần Raw SQL để tạo report cho nó performance. Tôi đồng ý với các anh luôn. Nhưng quan trọng là các anh đặt cái Raw SQL đó ở đâu? Các anh sẽ tự hào quăng luôn câu SQL đó vào trong code của các anh. Và tôi chúc các anh maintain nó vui vẻ cả phần đời còn lại của các anh.
Với tôi, quy tắc quan trọng nhất khi dùng ORM đó là khi anh không thể dùng ORM để viết một câu SQL anh muốn thì câu SQL đó phải nằm ở Database Server chứ không phải ở code của anh. Bởi vì, rõ ràng câu SQL đó nó gắn với một loại Database nhất định chứ không còn abstract đủ để dùng ORM nữa. Khi để câu SQL đó trong code tức là anh đã tự bắn vào "chim" mình, sau này khi có thay đổi thì anh ăn đạn đừng kêu trách ai.
Thế thôi. Đó là ý của tôi. Tầm nhìn nó phụ thuộc vào vị trí các anh đứng. Luôn nhớ là như vậy.

Tôi chém gió chứ có phải bảo vệ luận văn đâu mà anh kêu tôi đưa luận điểm với bench test. Mấy anh làm quá.
Tôi có nói gì về nosql đâu nhỉ? Tôi chỉ nói nhiều khi do politics trong công ty chef mới lên muốn có nguồn gió mới đổi sql thành nosql mặc dù sql nó chả có vấn đề gì thì sao lại chửi tôi nhỉ? Hay anh chửi lộn tôi với ai thế.
phần 3: GetUserByID, không thể select theo từng field vì khi đó rất khó maintain, nhưng cũng ko thể select * nếu table quá lớn. Giải pháp tôi từng làm cho team đơn giản là tách theo từng cụm. Ví dụ GetAll -> UserEntity, GetCredential -> UserCredentialEntity, GetContact -> UserContactEntity, GetProfile -> UserProfileEntity. Nếu cần 2 loại entity sẽ GetAll. Tất nhiên nó ko tối ưu, nhưng nó sẽ cân bằng cho cả performance và maintainance.
Tôi đồng ý khi cần nhanh, rất nhanh thì tối ưu hết tất cả và dùng raw sql là cần thiết như tôi đã ghi ở trên. Và thật sự tôi cũng không may mắn dẫn được đội 500 dev nên cũng không biết nó khủng cỡ nào. Bạn thật quá hạnh phúc.phần 2: ORM nó có nhiều tác dụng hơn vậy nhiều. Tất nhiên nó cũng có trade off, đó là performance. Cái anh đang nói thì chỉ cần query builder là đủ, tôi là dev trong 1 repo có 500 dev, vẫn đang dùng query builder thay vì ORM vì vấn đề performance.
Z là có test của bác trên r tôi ko cần viết benchmark vs bàn cãi thêm j nữa nha.@gaveezy: Rồi cám ơn bạn rất nhiều luôn. Như vậy tôi đã bị đập vào mặt là execution lệch 5ms và fetch time là 20ms. Như tôi chém gió là 0ms thì là "xạo lìn" (không phải tôi cố tình "xạo lìn" mà tôi test trên database tôi có đếch hiểu sao nó có 0ms (execution time) thôi. Tôi đã lựa cái bảng to nhất tôi có rồi).
Giờ tôi đợi tiếp anh @katoshi với anh @quandaso chứng minh tiếp là lệch khoảng bao nhiêu ms nũa.
Vậy đúng như ý tôi muốn hỏi và chứng minh giữa select * với select fied
@Edit: Tôi tìm ra lỗi của tôi rồi. Trên tool nó hiện 00:00:00 mà tôi đọc thành 00:00:00.0000. Xin lỗi anh em tức là có lệch vài ms. Nhưng tôi vẫn để bài viết như cũ không sửa nhé.
Test như này k ổn đâu thím, Query lần 2 trên cùng 1 bảng thì đã có caching rồi. Thím test lại thử xemVài giây là sao, đối với tôi vài giây lệch là hệ thống treo cmnr, thậm chí response trả về > 100ms thôi đã là không được rồi. Khi hệ thống nó scale lên 15M/20M request trên ngày ông sẽ hiểu dù 20ms nó đã đáng giá như nào.
Tôi ko biết ông đã vận hành hệ thống bao giờ chưa, nếu chưa tôi quay lại cái video cho ông mở rộng tầm mắt, khi select * 1 triệu bản ghi và select id nó khác nhau nhiều như thế nào
Kết quả select * mất 48s, select id mất 1.6 giây tức là nhanh gấp 30 lần. Tận 30 lần đấy![]()
. Ngày xưa em nhớ xài oracle thì select * và select field hầu như không chênh lệch quá nhiều 

Select id nó là trường index, nên coi như nó cache sẵn rồi, đâu phải query trước rồi cái sau mới cache đâu bạn. Chính vì cache/index nó select ra mới nhanh, chứ select * bao gồm cả trường index cả trường không index thì cache lúc đấy ko hiệu quả nữa rồi. Thế mới nói select từng field nó tốt hơn, vì tận dụng đc index và cache của mysql. Hoặc là nếu trường nào cần select theo nhóm ví dụ phone,name thì đánh index theo 2 trường đóTest như này k ổn đâu thím, Query lần 2 trên cùng 1 bảng thì đã có caching rồi. Thím test lại thử xem. Ngày xưa em nhớ xài oracle thì select * và select field hầu như không chênh lệch quá nhiều
@còn về ORM hay Raw SQL thì rõ ràng là ORM rồi, SQL chỉ viết khi thực sự cần tối ưu, dễ bảo trì bảo dưỡng, đỡ hỏng vặt, tưởng tượng 1 ngày công ty thím tuyển vài ba đứa newbie/junior, mà task yêu cầu viết 1 câu SQL hơi complex 1 tí thì tụi nó có mà ngồi đến năm sau cũng chưa viết ra đâu nhé![]()
![]()
![]()
Đấy là ý tôi muốn trình bày. Cái chính là như anh trình bày, 1 cái GetUserById nó phân nhánh thành 4, 5 hàm như thế. Rồi mỗi khi có cái củ cải gì mới, thằng Dev nó lại định nghĩa một cái hàm mới . Đến cuối cùng nó là một đám hổ lốn chỉ để đưa về thông tin của một User. Mà đấy chỉ là cho 1 User thôi í, giờ chúng ta scale lên 10 Entities hay 100 Entities (như Order, Product, Role...) thì code nó phình ra tới mức nào nên tôi chỉ nói là tôi chọn hướng tối ưu theo cách nhìn của tôi chứ tôi không chọn theo hướng lợi thêm được vài giây (tôi không dám nói milli giây luôn vì sẽ có thằng nhảy vào chửi tiếp). Và bằng chứng là các hệ thống tôi chịu trách nhiệm vẫn vận hành tốt.
Tôi ví dụ một thằng tôi đã làm là ADAC ở Đức nhé. Đây là một dịch vụ khởi nguồn là dịch vụ kéo xe bị hư giữa đường và giờ nó thành một hệ thống khổng lồ bán đủ thứ trên đời trừ phim xxx. Tôi cũng chả bao giờ hỏi tới là có bao nhiêu request một ngày nên tôi không chắc về lượng request đâu nhưng tôi chỉ biết ở Đức thằng này là dịch vụ lớn duy nhất về mảng này.
90tr dân Đức hàng ngày lên đây mua sắm bảo hiểm, dịch vụ, gọi báo lỗi xe,... thì tôi nghĩ chắc cũng đông đông và nó chả có vấn đề mịa gì về performance cả.
Cả hệ thống đếch có tối ưu mịa gì với raw sql cả. Select fields thì có trong các trường hợp đặc biệt vì yêu cầu thôi (mà rất ít vì toàn đọc chủ yếu từ cache ra). Còn report thì những gì cần nhiều thời gian thì như tôi đã nói ở trên.
Các hệ thống nó tách biệt nhau ra, chạy trên các server khác nhau, thêm vào load balancer, cache system, replication tôi thật sự không hiểu mấy anh cứ khè mấy chục ms với tôi làm gì. Tôi đếch hiểu mấy hệ thống của các anh sao nó phải phụ thuộc quá nhiều vào Database server như thế.
Tôi thấy vấn đề nó chỉ nằm ở 20-30 dev tụi nó trình độ khác nhau. Quản mới là mệt, sẽ có 2,3 thằng nerd như các anh suốt ngày hò hét với tui về performance cũng có 2,3 thằng nó kệ mẹ cuộc đời check in vô phát sập mẹ luôn cái dev. Thế thôi.
Tôi đồng ý khi cần nhanh, rất nhanh thì tối ưu hết tất cả và dùng raw sql là cần thiết như tôi đã ghi ở trên. Và thật sự tôi cũng không may mắn dẫn được đội 500 dev nên cũng không biết nó khủng cỡ nào. Bạn thật quá hạnh phúc.
) Thật sự trong 1 database thì việc phải tách table ra nhiều entity cũng không thường xảy ra vì không nhiều table phải chia nhỏ như vậy, ngay trong ví dụ của anh thì Order và Role hoàn toàn có thể select *. Cái điều này mình cũng khúc mắc bao lâu nay, mong các bác chỉ dạychốt lại e thấy bác 4nh7i3m nói khá đúng cho các trường hợp normal, vậy xin mạn phép hỏi bác (và các bác khác nữa) mấy case mà các bác trên này có hỏi:
- xử lý ntn với gọi các service với nhau - có nên gọi không?
- với các lệnh Join thì đặt ở repository nào của table nào?

GetUserById select theo từng field cho từng trường hợp nếu dùng EF Core + Automapper Projection vẫn làm dc nhé, lúc đó chỉ cần đưa vào từng IMapper instance có profile khác nhau là select field khác nhau liền. Tất nhiên output của hàm GetUserById phải định nghĩa đủ props cho tất cả các trường hợp, nhưng câu query mà EF Core generate ra thì tuỳ vô IMapper instancephần 1: có người test rồi.
phần 2: ORM nó có nhiều tác dụng hơn vậy nhiều. Tất nhiên nó cũng có trade off, đó là performance. Cái anh đang nói thì chỉ cần query builder là đủ, tôi là dev trong 1 repo có 500 dev, vẫn đang dùng query builder thay vì ORM vì vấn đề performance.
phần 3: GetUserByID, không thể select theo từng field vì khi đó rất khó maintain, nhưng cũng ko thể select * nếu table quá lớn. Giải pháp tôi từng làm cho team đơn giản là tách theo từng cụm. Ví dụ GetAll -> UserEntity, GetCredential -> UserCredentialEntity, GetContact -> UserContactEntity, GetProfile -> UserProfileEntity. Nếu cần 2 loại entity sẽ GetAll. Tất nhiên nó ko tối ưu, nhưng nó sẽ cân bằng cho cả performance và maintainance.
xin link tham khảo được ko ạGetUserById select theo từng field cho từng trường hợp nếu dùng EF Core + Automapper Projection vẫn làm dc nhé, lúc đó chỉ cần đưa vào từng IMapper instance có profile khác nhau là select field khác nhau liền. Tất nhiên output của hàm GetUserById phải định nghĩa đủ props cho tất cả các trường hợp, nhưng câu query mà EF Core generate ra thì tuỳ vô IMapper instance
chốt lại e thấy bác 4nh7i3m nói khá đúng cho các trường hợp normal, vậy xin mạn phép hỏi bác (và các bác khác nữa) mấy case mà các bác trên này có hỏi:
- xử lý ntn với gọi các service với nhau - có nên gọi không?
- với các lệnh Join thì đặt ở repository nào của table nào?
Cái điều này mình cũng khúc mắc bao lâu nay, mong các bác chỉ dạy![]()

using (MyDbContext ctx = new MyDbContext())
{
var studentRep = new Repository<Student>(ctx);
var standardRep = new Repository<Standard>(ctx);
var studentToStandard = studentRep.GetAll().Join(standardRep.GetAll(),
student => student.StandardRefId,
standard => standard.StandardId,
(stud, stand) => new { Student=stud, Standard=stand }).ToList();
}
// ...
unitOfWork.CourseRepository.Insert(course);
unitOfWork.Save();
//...
unitOfWork.CourseRepository.Delete(id);
unitOfWork.Save();
// ...
unitOfWork.Dispose();
// ...
courseDAS.Insert(course);
//...
courseDAS.Delete(id);
đây nhé thím https://docs.automapper.org/en/stable/Queryable-Extensions.htmlxin link tham khảo được ko ạ
GetUserById select theo từng field cho từng trường hợp nếu dùng EF Core + Automapper Projection vẫn làm dc nhé, lúc đó chỉ cần đưa vào từng IMapper instance có profile khác nhau là select field khác nhau liền. Tất nhiên output của hàm GetUserById phải định nghĩa đủ props cho tất cả các trường hợp, nhưng câu query mà EF Core generate ra thì tuỳ vô IMapper instance
)
) tự cân đo đong đếm chán, chứ cũng không theo khuôn khổ nào. Cơ mà MVC thì vẫn cái khung chính là MVC 3 tầng thôi. Em thấy thằng Jhipster nó generate code cũng oke, nhìn theo nó làm practice cũng ổnchuẩn như thím nói. trade-off thôi nhưng vẫn có cách để workaround bằng cách tạo 1 object projection có các properties chính là EF Entities, sau đó khai báo mapper sẽ map tu properties qua output object, thủ công hơn xí nhưng mà lợi ích nhiều hơn, cách này mình hay dùng cho câu query join nhiều tables, và output properties lấy từ nhiều tablesko dùng EF nhưng đoán là object user chứa nhiều properties, thím chỉ fetch những cái nào cần, số còn lại null hết?
làm như vậy thì khó maintain, vì khi sử dụng object user đó phải biết những field nào đc fetch những field nào không.