Các lỗi phát triển cơ sở dữ liệu phổ biến được thực hiện bởi các nhà phát triển ứng dụng là gì?
Các lỗi phát triển cơ sở dữ liệu phổ biến được thực hiện bởi các nhà phát triển ứng dụng là gì?
Câu trả lời:
1. Không sử dụng các chỉ số thích hợp
Đây là một điều tương đối dễ dàng nhưng nó vẫn xảy ra mọi lúc. Khóa ngoại nên có chỉ mục trên chúng. Nếu bạn đang sử dụng một trường trong một trường, WHERE
bạn nên (có thể) có một chỉ mục trên đó. Các chỉ mục như vậy thường bao gồm nhiều cột dựa trên các truy vấn bạn cần thực hiện.
2. Không thực thi toàn vẹn tham chiếu
Cơ sở dữ liệu của bạn có thể khác nhau ở đây nhưng nếu cơ sở dữ liệu của bạn hỗ trợ tính toàn vẹn tham chiếu - có nghĩa là tất cả các khóa ngoại được đảm bảo để trỏ đến một thực thể tồn tại - bạn nên sử dụng nó.
Nó khá phổ biến để thấy sự thất bại này trên cơ sở dữ liệu MySQL. Tôi không tin MyISAM hỗ trợ nó. InnoDB nào. Bạn sẽ tìm thấy những người đang sử dụng MyISAM hoặc những người đang sử dụng InnoDB nhưng dù sao cũng không sử dụng nó.
Thêm ở đây:
3. Sử dụng các khóa chính tự nhiên thay vì thay thế (kỹ thuật)
Khóa tự nhiên là khóa dựa trên dữ liệu có ý nghĩa bên ngoài là duy nhất (bề ngoài). Ví dụ phổ biến là mã sản phẩm, mã tiểu bang hai chữ cái (Hoa Kỳ), số an sinh xã hội, v.v. Các khóa chính thay thế hoặc kỹ thuật là những khóa hoàn toàn không có ý nghĩa gì ngoài hệ thống. Chúng được phát minh hoàn toàn để xác định thực thể và thường là các trường tăng tự động (SQL Server, MySQL, các loại khác) hoặc các chuỗi (đáng chú ý nhất là Oracle).
Theo tôi bạn nên luôn luôn sử dụng các khóa thay thế. Vấn đề này đã được đưa ra trong những câu hỏi sau:
Đây là một chủ đề gây tranh cãi mà bạn sẽ không nhận được thỏa thuận chung. Mặc dù bạn có thể tìm thấy một số người, những người cho rằng khóa tự nhiên trong một số trường hợp vẫn ổn, nhưng bạn sẽ không tìm thấy bất kỳ lời chỉ trích nào về khóa thay thế ngoài việc được cho là không cần thiết. Đó là một nhược điểm nhỏ nếu bạn hỏi tôi.
Hãy nhớ rằng, thậm chí các quốc gia có thể ngừng tồn tại (ví dụ, Nam Tư).
4. Viết các truy vấn yêu cầu DISTINCT
làm việc
Bạn thường thấy điều này trong các truy vấn do ORM tạo. Nhìn vào đầu ra nhật ký từ Hibernate và bạn sẽ thấy tất cả các truy vấn bắt đầu bằng:
SELECT DISTINCT ...
Đây là một chút phím tắt để đảm bảo bạn không trả về các hàng trùng lặp và do đó nhận được các đối tượng trùng lặp. Đôi khi bạn sẽ thấy mọi người làm điều này là tốt. Nếu bạn thấy nó quá nhiều thì đó là một lá cờ đỏ thực sự. Không phải DISTINCT
là xấu hoặc không có ứng dụng hợp lệ. Nó thực hiện (trên cả hai tổng số) nhưng nó không phải là một đại diện thay thế hoặc một điểm dừng để viết các truy vấn chính xác.
Từ lý do tại sao tôi ghét DISTINCT :
Theo tôi, mọi thứ bắt đầu trở nên tồi tệ khi một nhà phát triển đang xây dựng truy vấn đáng kể, nối các bảng lại với nhau và đột nhiên anh ta nhận ra rằng có vẻ như anh ta đang bị trùng lặp (hoặc thậm chí nhiều hơn) và phản ứng tức thì của anh ta ... "giải pháp" cho "vấn đề" này của anh ấy là ném từ khóa DISTINCT và POOF tất cả những rắc rối của anh ấy biến mất.
5. Tổng hợp ủng hộ hơn tham gia
Một lỗi phổ biến khác của các nhà phát triển ứng dụng cơ sở dữ liệu là không nhận ra tổng hợp đắt hơn (nghĩa là GROUP BY
mệnh đề) có thể được so sánh với các phép nối.
Để cho bạn biết mức độ phổ biến của nó, tôi đã viết về chủ đề này nhiều lần ở đây và đã bị đánh giá thấp rất nhiều cho nó. Ví dụ:
Từ câu lệnh SQL - Nhóm tham gia vào nhóm vs vs bởi và có :
Truy vấn đầu tiên:
SELECT userid FROM userrole WHERE roleid IN (1, 2, 3) GROUP by userid HAVING COUNT(1) = 3
Thời gian truy vấn: 0,312 giây
Truy vấn thứ hai:
SELECT t1.userid FROM userrole t1 JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2 JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3 AND t1.roleid = 1
Thời gian truy vấn: 0,016 s
Đúng rồi. Phiên bản tham gia tôi đề xuất nhanh hơn hai mươi lần so với phiên bản tổng hợp.
6. Không đơn giản hóa các truy vấn phức tạp thông qua các khung nhìn
Không phải tất cả các nhà cung cấp cơ sở dữ liệu đều hỗ trợ các khung nhìn nhưng đối với những người làm như vậy, họ có thể đơn giản hóa rất nhiều các truy vấn nếu được sử dụng một cách thận trọng. Ví dụ: trong một dự án tôi đã sử dụng mô hình Đảng chung cho CRM. Đây là một kỹ thuật mô hình cực kỳ mạnh mẽ và linh hoạt nhưng có thể dẫn đến nhiều tham gia. Trong mô hình này có:
Thí dụ:
Vì vậy, có năm bảng được tham gia để liên kết Ted với chủ nhân của mình. Bạn cho rằng tất cả nhân viên là Người (không phải tổ chức) và cung cấp quan điểm của người trợ giúp này:
CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id
Và đột nhiên bạn có một cái nhìn rất đơn giản về dữ liệu bạn muốn nhưng trên một mô hình dữ liệu rất linh hoạt.
7. Không vệ sinh đầu vào
Đây là một trong những rất lớn. Bây giờ tôi thích PHP nhưng nếu bạn không biết những gì bạn đang làm thì thực sự dễ dàng tạo ra các trang web dễ bị tấn công. Không có gì tóm tắt nó tốt hơn câu chuyện về Bobby Bàn nhỏ .
Dữ liệu được cung cấp bởi người dùng bằng URL, dữ liệu biểu mẫu và cookie phải luôn được coi là thù địch và vệ sinh. Hãy chắc chắn rằng bạn đang nhận được những gì bạn mong đợi.
8. Không sử dụng báo cáo đã chuẩn bị
Các câu lệnh được chuẩn bị là khi bạn biên dịch một truy vấn trừ đi dữ liệu được sử dụng trong các phần chèn, cập nhật và WHERE
mệnh đề và sau đó cung cấp nó sau đó. Ví dụ:
SELECT * FROM users WHERE username = 'bob'
đấu với
SELECT * FROM users WHERE username = ?
hoặc là
SELECT * FROM users WHERE username = :username
tùy thuộc vào nền tảng của bạn.
Tôi đã thấy cơ sở dữ liệu đến đầu gối của họ bằng cách làm điều này. Về cơ bản, mỗi khi bất kỳ cơ sở dữ liệu hiện đại nào gặp phải một truy vấn mới, nó phải biên dịch nó. Nếu nó gặp một truy vấn mà nó đã thấy trước đó, thì bạn đang cho cơ sở dữ liệu cơ hội lưu trữ truy vấn đã biên dịch và kế hoạch thực hiện. Bằng cách thực hiện truy vấn rất nhiều, bạn cho cơ sở dữ liệu cơ hội để tìm ra điều đó và tối ưu hóa cho phù hợp (ví dụ: bằng cách ghim truy vấn đã biên dịch trong bộ nhớ).
Sử dụng các câu lệnh được chuẩn bị cũng sẽ cung cấp cho bạn số liệu thống kê có ý nghĩa về tần suất sử dụng một số truy vấn nhất định.
Các câu lệnh được chuẩn bị cũng sẽ bảo vệ bạn tốt hơn trước các cuộc tấn công tiêm nhiễm SQL.
9. Không bình thường hóa đủ
Chuẩn hóa cơ sở dữ liệu về cơ bản là quá trình tối ưu hóa thiết kế cơ sở dữ liệu hoặc cách bạn sắp xếp dữ liệu của mình thành các bảng.
Mới tuần này tôi đã chạy qua một số mã trong đó ai đó đã mã hóa một mảng và chèn nó vào một trường duy nhất trong cơ sở dữ liệu. Bình thường hóa đó sẽ là coi phần tử của mảng đó là một hàng riêng biệt trong bảng con (nghĩa là mối quan hệ một-nhiều).
Điều này cũng xuất hiện trong phương pháp tốt nhất để lưu trữ danh sách ID người dùng :
Tôi đã thấy trong các hệ thống khác rằng danh sách được lưu trữ trong một mảng PHP được tuần tự hóa.
Nhưng thiếu bình thường hóa có nhiều dạng.
Hơn:
10. Bình thường hóa quá nhiều
Điều này có vẻ như mâu thuẫn với điểm trước nhưng bình thường hóa, giống như nhiều thứ, là một công cụ. Nó là một phương tiện để kết thúc và không phải là kết thúc trong chính nó. Tôi nghĩ rằng nhiều nhà phát triển quên điều này và bắt đầu coi "phương tiện" là "kết thúc". Kiểm thử đơn vị là một ví dụ điển hình của việc này.
Tôi đã từng làm việc trên một hệ thống có hệ thống phân cấp rất lớn cho các khách hàng có nội dung như sau:
Licensee -> Dealer Group -> Company -> Practice -> ...
sao cho bạn phải tham gia khoảng 11 bảng với nhau trước khi bạn có thể nhận được bất kỳ dữ liệu có ý nghĩa nào. Đó là một ví dụ tốt về bình thường hóa đi quá xa.
Hơn nữa, cẩn thận và được coi là không chuẩn hóa có thể có lợi ích hiệu suất rất lớn nhưng bạn phải thực sự cẩn thận khi làm điều này.
Hơn:
11. Sử dụng vòng cung độc quyền
Một cung độc quyền là một lỗi phổ biến trong đó một bảng được tạo bằng hai hoặc nhiều khóa ngoại trong đó một và chỉ một trong số chúng có thể là không rỗng. Sai lầm lớn. Đối với một điều, nó trở nên khó khăn hơn nhiều để duy trì tính toàn vẹn dữ liệu. Rốt cuộc, ngay cả với tính toàn vẹn tham chiếu, không có gì ngăn cản hai hoặc nhiều khóa ngoại này được đặt (các ràng buộc kiểm tra phức tạp mặc dù).
Từ một hướng dẫn thực tế để thiết kế cơ sở dữ liệu quan hệ :
Chúng tôi đã khuyến cáo mạnh mẽ chống lại việc xây dựng hồ quang độc quyền bất cứ khi nào có thể, vì lý do chính đáng là họ có thể lúng túng khi viết mã và gây ra nhiều khó khăn bảo trì hơn.
12. Không thực hiện phân tích hiệu suất trên các truy vấn nào cả
Chủ nghĩa thực dụng trị vì tối cao, đặc biệt là trong thế giới cơ sở dữ liệu. Nếu bạn tuân thủ các nguyên tắc đến mức chúng trở thành giáo điều thì có lẽ bạn đã mắc sai lầm. Lấy ví dụ về các truy vấn tổng hợp từ trên. Phiên bản tổng hợp có thể trông "đẹp" nhưng hiệu suất của nó thì kém. Một so sánh hiệu suất nên đã kết thúc cuộc tranh luận (nhưng không phải vậy) nhưng quan trọng hơn: việc đưa ra những quan điểm thiếu hiểu biết như vậy ở nơi đầu tiên là không biết gì, thậm chí nguy hiểm.
13. Quá phụ thuộc vào các cấu trúc của UNION ALL và đặc biệt là UNION
Một UNION trong các thuật ngữ SQL chỉ đơn thuần ghép các tập dữ liệu đồng dạng, nghĩa là chúng có cùng loại và số cột. Sự khác biệt giữa chúng là UNION ALL là một cách ghép đơn giản và nên được ưu tiên bất cứ khi nào có thể trong khi UNION sẽ ngầm thực hiện một DISTINCT để loại bỏ các bộ dữ liệu trùng lặp.
ĐOÀN, như DISTINCT, có vị trí của họ. Có những ứng dụng hợp lệ. Nhưng nếu bạn thấy mình làm rất nhiều trong số đó, đặc biệt là trong các truy vấn con, thì có lẽ bạn đã làm sai điều gì đó. Đó có thể là một trường hợp xây dựng truy vấn kém hoặc mô hình dữ liệu được thiết kế kém buộc bạn phải làm những việc như vậy.
UNION, đặc biệt khi được sử dụng trong các phép nối hoặc truy vấn con phụ thuộc, có thể làm tê liệt cơ sở dữ liệu. Cố gắng tránh chúng bất cứ khi nào có thể.
14. Sử dụng điều kiện OR trong truy vấn
Điều này có vẻ vô hại. Rốt cuộc, AND vẫn ổn. HOẶC cũng nên ổn chứ? Sai lầm. Về cơ bản, một điều kiện AND giới hạn tập dữ liệu trong khi điều kiện OR phát triển nó nhưng không theo cách cho vay để tối ưu hóa. Đặc biệt là khi các điều kiện OR khác nhau có thể giao nhau, do đó buộc trình tối ưu hóa có hiệu quả đối với hoạt động DISTINCT trên kết quả.
Xấu:
... WHERE a = 2 OR a = 5 OR a = 11
Tốt hơn:
... WHERE a IN (2, 5, 11)
Bây giờ trình tối ưu hóa SQL của bạn có thể biến truy vấn đầu tiên thành truy vấn thứ hai một cách hiệu quả. Nhưng nó có thể không. Đừng làm điều đó.
15. Không thiết kế mô hình dữ liệu của họ để cho vay các giải pháp hiệu suất cao
Đây là một điểm khó để định lượng. Nó thường được quan sát bởi hiệu ứng của nó. Nếu bạn thấy mình viết các truy vấn sởn gai ốc cho các nhiệm vụ tương đối đơn giản hoặc các truy vấn tìm hiểu thông tin tương đối đơn giản không hiệu quả, thì có lẽ bạn có một mô hình dữ liệu kém.
Trong một số cách, điểm này tóm tắt tất cả những cái trước đó nhưng đó là một câu chuyện cảnh báo rằng việc thực hiện những việc như tối ưu hóa truy vấn thường được thực hiện trước tiên khi cần thực hiện lần thứ hai. Trước hết, bạn nên đảm bảo bạn có một mô hình dữ liệu tốt trước khi cố gắng tối ưu hóa hiệu suất. Như Knuth đã nói:
Tối ưu hóa sớm là gốc rễ của mọi tội lỗi
16. Sử dụng sai giao dịch cơ sở dữ liệu
Tất cả các thay đổi dữ liệu cho một quá trình cụ thể nên là nguyên tử. Tức là nếu hoạt động thành công, nó làm như vậy đầy đủ. Nếu thất bại, dữ liệu được giữ nguyên. - Không nên có khả năng thay đổi 'nửa vời'.
Lý tưởng nhất, cách đơn giản nhất để đạt được điều này là toàn bộ thiết kế hệ thống nên cố gắng hỗ trợ tất cả các thay đổi dữ liệu thông qua các câu lệnh INSERT / UPDATE / DELETE duy nhất. Trong trường hợp này, không cần xử lý giao dịch đặc biệt, vì công cụ cơ sở dữ liệu của bạn sẽ tự động làm như vậy.
Tuy nhiên, nếu bất kỳ quy trình nào yêu cầu nhiều câu lệnh được thực hiện như một đơn vị để giữ dữ liệu ở trạng thái nhất quán, thì Kiểm soát giao dịch thích hợp là cần thiết.
Cũng nên chú ý cẩn thận đến các mạng con về cách kết nối cơ sở dữ liệu của bạn và công cụ cơ sở dữ liệu tương tác trong vấn đề này.
17. Không hiểu mô hình 'dựa trên tập hợp'
Ngôn ngữ SQL tuân theo một mô hình cụ thể phù hợp với các loại vấn đề cụ thể. Các tiện ích mở rộng dành riêng cho nhà cung cấp khác nhau, ngôn ngữ đấu tranh để xử lý các vấn đề không đáng kể trong các ngôn ngữ như Java, C #, Delphi, v.v.
Sự thiếu hiểu biết này thể hiện ở một vài cách.
Xác định sự phân chia trách nhiệm rõ ràng và cố gắng sử dụng công cụ thích hợp để giải quyết từng vấn đề.
Lỗi thiết kế cơ sở dữ liệu và lập trình do các nhà phát triển thực hiện
Thiết kế và sử dụng cơ sở dữ liệu ích kỷ. Các nhà phát triển thường coi cơ sở dữ liệu là kho đối tượng liên tục cá nhân của họ mà không xem xét nhu cầu của các bên liên quan khác trong dữ liệu. Điều này cũng áp dụng cho các kiến trúc sư ứng dụng. Thiết kế cơ sở dữ liệu kém và tính toàn vẹn dữ liệu khiến các bên thứ ba làm việc với dữ liệu khó khăn và có thể làm tăng đáng kể chi phí vòng đời của hệ thống. Báo cáo và MIS có xu hướng là một người anh em họ nghèo trong thiết kế ứng dụng và chỉ được thực hiện như một suy nghĩ sau.
Lạm dụng dữ liệu không chuẩn hóa. Việc lạm dụng dữ liệu không chuẩn hóa và cố gắng duy trì dữ liệu trong ứng dụng là một công thức cho các vấn đề toàn vẹn dữ liệu. Sử dụng không bình thường một cách tiết kiệm. Không muốn thêm một tham gia vào một truy vấn không phải là một lý do cho việc không chuẩn hóa.
Sợ viết SQL. SQL không phải là khoa học tên lửa và thực sự khá giỏi trong việc thực hiện công việc của mình. Các lớp ánh xạ O / R khá tốt trong việc thực hiện 95% các truy vấn đơn giản và phù hợp với mô hình đó. Đôi khi SQL là cách tốt nhất để thực hiện công việc.
Chính sách 'Không thủ tục lưu trữ' giáo điều. Bất kể bạn có tin rằng các thủ tục được lưu trữ là xấu xa hay không, thái độ giáo điều này không có chỗ trong một dự án phần mềm.
Không hiểu thiết kế cơ sở dữ liệu. Bình thường hóa là bạn của bạn và nó không phải là khoa học tên lửa. Tham gia và cardinality là những khái niệm khá đơn giản - nếu bạn tham gia vào phát triển ứng dụng cơ sở dữ liệu thì thực sự không có lý do gì để không hiểu chúng.
Sử dụng quá mức và / hoặc phụ thuộc vào các thủ tục được lưu trữ.
Một số nhà phát triển ứng dụng xem các thủ tục được lưu trữ như một phần mở rộng trực tiếp của mã tầng giữa / mặt trước. Điều này dường như là một đặc điểm phổ biến trong các nhà phát triển ngăn xếp của Microsoft, (tôi là một, nhưng tôi đã phát triển từ đó) và tạo ra nhiều quy trình được lưu trữ để thực hiện logic nghiệp vụ và xử lý quy trình công việc phức tạp. Điều này được thực hiện tốt hơn nhiều ở nơi khác.
Các thủ tục được lưu trữ rất hữu ích khi đã được chứng minh một cách chính xác rằng một số yếu tố kỹ thuật thực sự cần phải sử dụng chúng (ví dụ: hiệu suất và bảo mật) Ví dụ: giữ tập hợp / lọc các tập dữ liệu lớn "gần với dữ liệu".
Gần đây tôi đã phải giúp duy trì và nâng cao một ứng dụng máy tính để bàn Delphi lớn, trong đó 70% logic và quy tắc kinh doanh được triển khai trong 1400 thủ tục lưu trữ SQL Server (phần còn lại trong trình xử lý sự kiện UI). Đây là một cơn ác mộng, chủ yếu là do việc giới thiệu thử nghiệm đơn vị hiệu quả cho TSQL, thiếu đóng gói và các công cụ kém (Trình gỡ lỗi, biên tập viên).
Làm việc với một nhóm Java trong quá khứ tôi nhanh chóng phát hiện ra rằng thường thì hoàn toàn ngược lại trong môi trường đó. Một kiến trúc sư Java đã từng nói với tôi: "Cơ sở dữ liệu dành cho dữ liệu, không phải mã.".
Ngày nay tôi nghĩ thật sai lầm khi không xem xét các procs được lưu trữ, nhưng chúng nên được sử dụng một cách tiết kiệm (không phải mặc định) trong các tình huống mà chúng cung cấp các lợi ích hữu ích (xem các câu trả lời khác).
Vấn đề số một? Họ chỉ kiểm tra trên cơ sở dữ liệu đồ chơi. Vì vậy, họ không biết rằng SQL của họ sẽ thu thập dữ liệu khi cơ sở dữ liệu trở nên lớn và ai đó phải đi cùng và sửa nó sau (âm thanh mà bạn có thể nghe thấy là nghiến răng).
Không sử dụng chỉ mục.
Hiệu suất kém gây ra bởi các truy vấn tương quan
Hầu hết thời gian bạn muốn tránh các truy vấn con tương quan. Một truy vấn con có tương quan nếu, trong truy vấn con, có một tham chiếu đến một cột từ truy vấn bên ngoài. Khi điều này xảy ra, truy vấn con được thực hiện ít nhất một lần cho mỗi hàng được trả về và có thể được thực thi nhiều lần hơn nếu các điều kiện khác được áp dụng sau khi điều kiện có chứa truy vấn con tương quan được áp dụng.
Tha thứ cho ví dụ giả định và cú pháp của Oracle, nhưng giả sử bạn muốn tìm tất cả các nhân viên đã được thuê trong bất kỳ cửa hàng nào của bạn kể từ lần cuối cùng cửa hàng bán được ít hơn 10.000 đô la mỗi ngày.
select e.first_name, e.last_name
from employee e
where e.start_date >
(select max(ds.transaction_date)
from daily_sales ds
where ds.store_id = e.store_id and
ds.total < 10000)
Truy vấn con trong ví dụ này tương quan với truy vấn bên ngoài bởi store_id và sẽ được thực thi cho mọi nhân viên trong hệ thống của bạn. Một cách mà truy vấn này có thể được tối ưu hóa là chuyển truy vấn con sang chế độ xem nội tuyến.
select e.first_name, e.last_name
from employee e,
(select ds.store_id,
max(s.transaction_date) transaction_date
from daily_sales ds
where ds.total < 10000
group by s.store_id) dsx
where e.store_id = dsx.store_id and
e.start_date > dsx.transaction_date
Trong ví dụ này, truy vấn trong mệnh đề from hiện là dạng xem nội tuyến (một số cú pháp cụ thể của Oracle) và chỉ được thực hiện một lần. Tùy thuộc vào mô hình dữ liệu của bạn, truy vấn này có thể sẽ thực thi nhanh hơn nhiều. Nó sẽ thực hiện tốt hơn truy vấn đầu tiên khi số lượng nhân viên tăng lên. Truy vấn đầu tiên thực sự có thể hoạt động tốt hơn nếu có ít nhân viên và nhiều cửa hàng (và có lẽ nhiều cửa hàng không có nhân viên) và bảng Daily_sales được lập chỉ mục trên store_id. Đây không phải là một kịch bản có khả năng nhưng cho thấy cách truy vấn tương quan có thể thực hiện tốt hơn so với một thay thế.
Tôi đã thấy các nhà phát triển cơ sở tương quan các truy vấn con nhiều lần và nó thường có tác động nghiêm trọng đến hiệu suất. Tuy nhiên, khi loại bỏ một truy vấn con tương quan, hãy chắc chắn xem xét kế hoạch giải thích trước và sau để đảm bảo bạn không làm cho hiệu suất kém hơn.
Sử dụng Access thay vì cơ sở dữ liệu "thực". Có rất nhiều cơ sở dữ liệu nhỏ và thậm chí miễn phí tuyệt vời như SQL Express , MySQL và SQLite sẽ hoạt động và mở rộng quy mô tốt hơn nhiều. Ứng dụng thường cần mở rộng theo những cách bất ngờ.
Sử dụng Excel để lưu trữ (số lượng lớn) dữ liệu.
Tôi đã thấy các công ty nắm giữ hàng ngàn hàng và sử dụng nhiều bảng tính (do giới hạn hàng là 65535 trên các phiên bản Excel trước).
Excel rất phù hợp cho các báo cáo, trình bày dữ liệu và các tác vụ khác, nhưng không nên được coi là cơ sở dữ liệu.
Tôi muốn thêm: Yêu thích mã "Thanh lịch" hơn mã hiệu suất cao. Mã hoạt động tốt nhất đối với cơ sở dữ liệu thường xấu đối với mắt của nhà phát triển ứng dụng.
Tin rằng vô nghĩa về tối ưu hóa sớm. Cơ sở dữ liệu phải xem xét hiệu suất trong thiết kế ban đầu và trong bất kỳ sự phát triển tiếp theo nào. Hiệu suất là 50% thiết kế cơ sở dữ liệu (40% là toàn vẹn dữ liệu và 10% cuối cùng là bảo mật) theo ý kiến của tôi. Cơ sở dữ liệu không được xây dựng từ dưới lên để thực hiện sẽ hoạt động kém khi người dùng thực và lưu lượng truy cập thực được đặt vào cơ sở dữ liệu. Tối ưu hóa sớm không có nghĩa là không tối ưu hóa! Điều đó không có nghĩa là bạn nên viết mã hầu như sẽ luôn hoạt động kém bởi vì bạn thấy nó dễ dàng hơn (ví dụ, các con trỏ không bao giờ được phép trong cơ sở dữ liệu sản xuất trừ khi tất cả các lỗi khác đều thất bại). Điều đó có nghĩa là bạn không cần nhìn vào việc vắt kiệt chút hiệu suất cuối cùng cho đến khi bạn cần. Rất nhiều điều được biết về những gì sẽ hoạt động tốt hơn trên cơ sở dữ liệu,
Không sử dụng truy vấn tham số. Chúng khá tiện dụng trong việc ngăn chặn SQL Injection .
Đây là một ví dụ cụ thể về việc không vệ sinh dữ liệu đầu vào, được đề cập trong câu trả lời khác.
Tôi ghét nó khi các nhà phát triển sử dụng các câu lệnh chọn lồng nhau hoặc thậm chí các hàm trả về kết quả của câu lệnh chọn bên trong phần "CHỌN" của truy vấn.
Tôi thực sự ngạc nhiên Tôi không thấy điều này ở bất cứ nơi nào khác ở đây, có lẽ tôi đã bỏ qua nó, mặc dù @adam có một vấn đề tương tự được chỉ ra.
Thí dụ:
SELECT
(SELECT TOP 1 SomeValue FROM SomeTable WHERE SomeDate = c.Date ORDER BY SomeValue desc) As FirstVal
,(SELECT OtherValue FROM SomeOtherTable WHERE SomeOtherCriteria = c.Criteria) As SecondVal
FROM
MyTable c
Trong trường hợp này, nếu MyTable trả về 10000 hàng, kết quả sẽ như thể truy vấn chỉ chạy 20001 truy vấn, vì nó phải chạy truy vấn ban đầu cộng với truy vấn từng bảng khác nhau cho mỗi dòng kết quả.
Các nhà phát triển có thể thoát khỏi công việc này trong môi trường phát triển khi họ chỉ trả về một vài hàng dữ liệu và các bảng phụ thường chỉ có một lượng dữ liệu nhỏ, nhưng trong môi trường sản xuất, loại truy vấn này có thể trở nên tốn kém theo cấp số nhân dữ liệu được thêm vào các bảng.
Một ví dụ tốt hơn (không nhất thiết phải hoàn hảo) sẽ là một cái gì đó như:
SELECT
s.SomeValue As FirstVal
,o.OtherValue As SecondVal
FROM
MyTable c
LEFT JOIN (
SELECT SomeDate, MAX(SomeValue) as SomeValue
FROM SomeTable
GROUP BY SomeDate
) s ON c.Date = s.SomeDate
LEFT JOIN SomeOtherTable o ON c.Criteria = o.SomeOtherCriteria
Điều này cho phép các trình tối ưu hóa cơ sở dữ liệu trộn lẫn dữ liệu lại với nhau, thay vì yêu cầu trên mỗi bản ghi từ bảng chính và tôi thường tìm thấy khi phải sửa mã khi sự cố này được tạo, tôi thường kết thúc việc tăng tốc độ truy vấn lên 100% hoặc nhiều hơn trong khi đồng thời giảm sử dụng CPU và bộ nhớ.
Đối với cơ sở dữ liệu dựa trên SQL:
Không sao lưu trước khi sửa một số vấn đề bên trong cơ sở dữ liệu sản xuất.
Sử dụng các lệnh DDL trên các đối tượng được lưu trữ (như bảng, dạng xem) trong các thủ tục được lưu trữ.
Sợ sử dụng Proc được lưu trữ hoặc sợ sử dụng truy vấn ORM ở bất cứ nơi nào hiệu quả hơn / phù hợp để sử dụng.
Bỏ qua việc sử dụng một trình lược tả cơ sở dữ liệu, có thể cho bạn biết chính xác truy vấn ORM của bạn cuối cùng được chuyển thành gì và do đó xác minh logic hoặc thậm chí để gỡ lỗi khi không sử dụng ORM.
Không làm đúng mức bình thường hóa . Bạn muốn đảm bảo rằng dữ liệu không bị trùng lặp và bạn sẽ chia dữ liệu thành khác nhau khi cần. Bạn cũng cần đảm bảo rằng bạn không theo dõi quá trình bình thường hóa vì điều đó sẽ ảnh hưởng đến hiệu suất.
Coi cơ sở dữ liệu chỉ là một cơ chế lưu trữ (tức là thư viện bộ sưu tập được tôn vinh) và do đó phụ thuộc vào ứng dụng của họ (bỏ qua các ứng dụng khác có chung dữ liệu)
1 - Không cần thiết sử dụng hàm trên một giá trị trong mệnh đề where với kết quả của chỉ mục đó không được sử dụng.
Thí dụ:
where to_char(someDate,'YYYYMMDD') between :fromDate and :toDate
thay vì
where someDate >= to_date(:fromDate,'YYYYMMDD') and someDate < to_date(:toDate,'YYYYMMDD')+1
Và ở mức độ thấp hơn: Không thêm các chỉ mục chức năng vào các giá trị cần chúng ...
2 - Không thêm các ràng buộc kiểm tra để đảm bảo tính hợp lệ của dữ liệu. Các ràng buộc có thể được sử dụng bởi trình tối ưu hóa truy vấn và chúng THỰC SỰ giúp đỡ để đảm bảo rằng bạn có thể tin tưởng vào bất biến của mình. Không có lý do gì để không sử dụng chúng.
3 - Thêm các cột không chuẩn hóa vào các bảng khỏi sự lười biếng thuần túy hoặc áp lực thời gian. Mọi thứ thường không được thiết kế theo cách này, nhưng phát triển thành này. Kết quả cuối cùng, không có thất bại, là một tấn công việc cố gắng dọn dẹp mớ hỗn độn khi bạn bị cắn bởi tính toàn vẹn dữ liệu bị mất trong các diễn biến trong tương lai.
Hãy nghĩ về điều này, một bảng không có dữ liệu rất rẻ để thiết kế lại. Một bảng có vài triệu bản ghi không có tính toàn vẹn ... không quá rẻ để thiết kế lại. Do đó, thực hiện thiết kế chính xác khi tạo cột hoặc bảng được khấu hao theo tỷ lệ.
4 - không quá nhiều về cơ sở dữ liệu mỗi se nhưng thực sự gây phiền nhiễu. Không quan tâm đến chất lượng mã của SQL. Thực tế là SQL của bạn được thể hiện bằng văn bản không giúp bạn ẩn logic trong hàng đống thuật toán thao tác chuỗi. Hoàn toàn có thể viết SQL bằng văn bản theo cách mà người lập trình viên của bạn thực sự có thể đọc được.
Điều này đã được nói trước đây, nhưng: chỉ mục, chỉ mục, chỉ mục . Tôi đã thấy rất nhiều trường hợp ứng dụng web doanh nghiệp hoạt động kém đã được khắc phục bằng cách chỉ cần thực hiện một chút hồ sơ (để xem bảng nào đang bị ảnh hưởng nhiều), sau đó thêm chỉ mục vào các bảng đó. Điều này thậm chí không đòi hỏi nhiều về kiến thức viết SQL và mức chi trả là rất lớn.
Tránh trùng lặp dữ liệu như bệnh dịch hạch. Một số người ủng hộ rằng một chút trùng lặp sẽ không bị tổn thương và sẽ cải thiện hiệu suất. Xin chào, tôi không nói rằng bạn phải tra tấn lược đồ của mình thành Dạng thông thường thứ ba, cho đến khi nó quá trừu tượng đến nỗi ngay cả DBA cũng không biết chuyện gì đang xảy ra. Chỉ cần hiểu rằng bất cứ khi nào bạn sao chép một tập hợp tên hoặc mã zip hoặc mã vận chuyển, các bản sao SILL sẽ không đồng bộ với nhau. Nó sẽ xảy ra. Và sau đó bạn sẽ tự đá mình khi bạn chạy tập lệnh bảo trì hàng tuần.
Và cuối cùng: sử dụng một quy ước đặt tên rõ ràng, nhất quán, trực quan. Theo cùng một cách mà một đoạn mã được viết tốt sẽ có thể đọc được, một lược đồ hoặc truy vấn SQL tốt sẽ có thể đọc được và thực tế cho bạn biết những gì nó đang làm, ngay cả khi không có nhận xét. Bạn sẽ cảm ơn bản thân trong sáu tháng, khi bạn phải bảo trì trên bàn. "SELECT account_number, billing_date FROM national_accounts"
làm việc với vô cùng dễ dàng hơn so với "CHỌN ACCNTNBR, BILLDAT TỪ NTNLACCTS".
Lỗi phổ biến nhất tôi từng thấy trong hai mươi năm: không lên kế hoạch trước. Nhiều nhà phát triển sẽ tạo cơ sở dữ liệu và các bảng, sau đó liên tục sửa đổi và mở rộng các bảng khi họ xây dựng các ứng dụng. Kết quả cuối cùng thường là một mớ hỗn độn và không hiệu quả và khó làm sạch hoặc đơn giản hóa sau này.
a) Các giá trị
truy vấn mã hóa cứng trong chuỗi b) Đưa mã truy vấn cơ sở dữ liệu vào hành động "OnButtonPress" trong ứng dụng Windows Forms
Tôi đã thấy cả hai.
Nghĩ rằng họ là các DBA và nhà thiết kế / mô hình dữ liệu khi họ không có sự truyền bá chính thức dưới bất kỳ hình thức nào trong các lĩnh vực đó.
Nghĩ rằng dự án của họ không yêu cầu DBA vì những thứ đó hoàn toàn dễ dàng / tầm thường.
Thất bại trong việc phân biệt chính xác giữa các công việc nên được thực hiện trong cơ sở dữ liệu và công việc nên được thực hiện trong ứng dụng.
Không xác nhận sao lưu, hoặc không sao lưu.
Nhúng SQL thô vào mã của họ.
Dưới đây là liên kết đến video có tên ' Lỗi phát triển cơ sở dữ liệu cổ điển và năm cách khắc phục chúng ' của Scott Walz
Không có hiểu biết về mô hình đồng thời cơ sở dữ liệu và làm thế nào điều này ảnh hưởng đến sự phát triển. Thật dễ dàng để thêm các chỉ mục và điều chỉnh các truy vấn sau khi thực tế. Tuy nhiên, các ứng dụng được thiết kế mà không có sự xem xét thích hợp cho các điểm nóng, tranh chấp tài nguyên và hoạt động chính xác (Giả sử những gì bạn vừa đọc vẫn hợp lệ!) Có thể yêu cầu thay đổi đáng kể trong cơ sở dữ liệu và tầng ứng dụng để sửa sau.
Không hiểu làm thế nào một DBMS hoạt động dưới mui xe.
Bạn không thể lái gậy đúng cách mà không hiểu cách ly hợp hoạt động. Và bạn không thể hiểu làm thế nào để sử dụng Cơ sở dữ liệu mà không hiểu rằng bạn thực sự chỉ đang ghi vào một tệp trên đĩa cứng của bạn.
Đặc biệt:
Bạn có biết Chỉ số cụm là gì không? Bạn đã nghĩ về nó khi bạn thiết kế lược đồ của bạn?
Bạn có biết làm thế nào để sử dụng chỉ mục đúng cách? Làm thế nào để sử dụng lại một chỉ mục? Bạn có biết Chỉ số bao phủ là gì không?
Thật tuyệt vời, bạn có chỉ số. Làm thế nào lớn là 1 hàng trong chỉ mục của bạn? Chỉ số sẽ lớn đến mức nào khi bạn có nhiều dữ liệu? Điều đó sẽ dễ dàng phù hợp với bộ nhớ? Nếu nó không vô dụng như một chỉ mục.
Bạn đã bao giờ sử dụng GIẢI THÍCH trong MySQL chưa? Tuyệt quá. Bây giờ hãy thành thật với chính mình: Bạn đã hiểu một nửa những gì bạn đã thấy chưa? Không, bạn có thể đã không. Khắc phục điều đó.
Bạn có hiểu Cache truy vấn không? Bạn có biết điều gì làm cho một truy vấn không lưu trữ được không?
Bạn đang sử dụng MyISAM? Nếu bạn CẦN tìm kiếm toàn văn, MyISAM's dù sao cũng là rác rưởi. Sử dụng nhân sư. Sau đó chuyển sang Inno.