Tại sao sử dụng cơ sở dữ liệu thay vì chỉ lưu dữ liệu của bạn vào đĩa?


193

Thay vì cơ sở dữ liệu, tôi chỉ tuần tự hóa dữ liệu của mình thành JSON, lưu và tải nó vào đĩa khi cần thiết. Tất cả việc quản lý dữ liệu được thực hiện trên chính chương trình, nhanh hơn VÀ dễ dàng hơn so với sử dụng các truy vấn SQL. Vì lý do đó tôi chưa bao giờ hiểu tại sao cơ sở dữ liệu là cần thiết cả.

Tại sao người ta nên sử dụng cơ sở dữ liệu thay vì chỉ lưu dữ liệu vào đĩa?


61
Nếu việc quản lý các mối quan hệ của dữ liệu trong ứng dụng của bạn thực sự nhanh hơn so với thực hiện trong cơ sở dữ liệu (điều mà tôi thấy cực kỳ khó tin) thì bạn cần phải đọc SQL và chuẩn hóa cơ sở dữ liệu. Những gì bạn đang trải nghiệm có lẽ là tác dụng phụ của cơ sở dữ liệu được thiết kế khủng khiếp.
yannis

68
Bạn không cần một cơ sở dữ liệu trong kịch bản bạn đang mô tả vì tập dữ liệu của bạn là không đáng kể. Cơ sở dữ liệu có nghĩa là cho các tập dữ liệu phức tạp hơn, nếu tất cả những gì bạn làm là đọc và hiển thị một danh sách, phương pháp của bạn sẽ hoạt động.
yannis

16
Những điều kiện chủng tộc bạn có thể gặp phải, và bạn đã sẵn sàng cho điều đó? Bạn có muốn mở rộng quy mô qua một máy chủ web không? Gói dự phòng của bạn là gì nếu máy chủ của bạn bị lỗi? Câu trả lời của bạn cho tất cả những câu hỏi này có thể sẽ tốt hơn nếu bạn có cơ sở dữ liệu hơn là nếu bạn không có. Ngoài ra, nếu bạn đã từng học về cách sử dụng cơ sở dữ liệu, tôi đoán là bạn sẽ thấy "dễ hơn sử dụng truy vấn SQL" nên được sửa đổi thành "dễ hơn sử dụng truy vấn SQL nếu bạn không hiểu SQL".
btilly

37
Cơ sở dữ liệu lưu trữ dữ liệu vào đĩa nào. Đó chỉ là kết quả cuối cùng của một sự phát triển tự nhiên của các hệ thống để lưu trữ dữ liệu có cấu trúc vào tệp. Rất có thể nếu bạn bắt đầu sử dụng các tệp để lưu trữ dữ liệu có cấu trúc của mình, bạn sẽ thấy mình phát minh lại các tính năng đã được phát triển trong cơ sở dữ liệu. Vậy tại sao không chỉ sử dụng một cơ sở dữ liệu từ đầu?
Benedict

13
Tùy thuộc vào cách dự án của bạn phát triển, bạn có thể thấy mình phải đối phó với những thứ như truy cập đồng thời và rollback. Họ nghe có vẻ tầm thường, nhưng không. Khi bạn hoàn thành việc giải quyết chúng, bạn sẽ thấy về cơ bản bạn đã viết một cơ sở dữ liệu. Bạn có thực sự muốn kinh doanh cơ sở dữ liệu, hoặc một doanh nghiệp khác không?
jwernerny

Câu trả lời:


280
  1. Bạn có thể truy vấn dữ liệu trong cơ sở dữ liệu (đặt câu hỏi).
  2. Bạn có thể tra cứu dữ liệu từ cơ sở dữ liệu tương đối nhanh chóng.
  3. Bạn có thể liên kết dữ liệu từ hai bảng khác nhau với nhau bằng cách sử dụng THAM GIA.
  4. Bạn có thể tạo các báo cáo có ý nghĩa từ dữ liệu trong cơ sở dữ liệu.
  5. Dữ liệu của bạn có cấu trúc tích hợp sẵn.
  6. Thông tin của một loại nhất định luôn được lưu trữ chỉ một lần.
  7. Cơ sở dữ liệu là ACID .
  8. Cơ sở dữ liệu có khả năng chịu lỗi.
  9. Cơ sở dữ liệu có thể xử lý các tập dữ liệu rất lớn.
  10. Cơ sở dữ liệu đồng thời; nhiều người dùng có thể sử dụng chúng cùng một lúc mà không làm hỏng dữ liệu.
  11. Cơ sở dữ liệu quy mô tốt.

Nói tóm lại, bạn được hưởng lợi từ một loạt các công nghệ nổi tiếng, đã được chứng minh được phát triển qua nhiều năm bởi nhiều người rất thông minh.

Nếu bạn lo lắng rằng cơ sở dữ liệu quá mức cần thiết, hãy kiểm tra SQLite.


21
6. Chuẩn hóa, 7. Xem liên kết, 8. Đọc về khả năng chịu lỗi. Ồ, và trước khi bạn bị cuốn vào cơn sốt NoQuery, hãy tìm hiểu về cơ sở dữ liệu SQL; nhận biết chúng theo cách riêng của chúng. Bạn sẽ hiểu. Nếu bạn chỉ nói về dữ liệu cấu hình đơn giản, JSON có thể là tất cả những gì bạn cần. Nhưng có nhiều loại dữ liệu khác ngoài các cài đặt chương trình.
Robert Harvey

25
Theo như không an toàn khi có hai chương trình chỉnh sửa dữ liệu cùng một lúc, đó là một phần lý do tại sao cơ sở dữ liệu tồn tại. Nếu bạn có nhu cầu này (và một số hoặc tất cả các nhu cầu khác mà tôi đã đề cập), bạn sẽ rất vui vì bạn không phải phát minh lại tất cả những điều này.
Robert Harvey

23
@Dokkat Không cần thiết, không có gì. Nếu cách tiếp cận của bạn làm việc cho bạn, bằng mọi cách đi cho nó. Tuy nhiên, tôi nên đề cập rằng hầu hết các rdbms đều hỗ trợ các kho lưu trữ dựa trên bộ nhớ, bạn có thể tải mọi thứ bạn cần trong bộ nhớ khi ứng dụng của bạn thức dậy (như bạn đã làm) và truy vấn chúng như một cơ sở dữ liệu thông thường (giữ tất cả các lợi ích mà Robert đã đề cập ).
yannis

28
Nói cách khác, đôi khi bạn cần một cái lều, nhưng đôi khi bạn cần một ngôi nhà, và xây dựng một ngôi nhà là một trò chơi bóng hoàn toàn khác so với việc dựng lều.
Robert Harvey

49
@Dokkat khi mọi người đề cập đến sự cố, họ có nghĩa là những thứ như ... CPU của bạn đã bị hỏng giữa chừng khi viết tệp "cơ sở dữ liệu" của bạn. Chuyện gì xảy ra bây giờ? Nhiều khả năng tệp của bạn bị hỏng / không thể đọc được (ít nhất, nó có thể không còn phù hợp với định dạng của riêng bạn) và bạn cần khôi phục lại một bản sao lưu (trong khi hầu hết các DB "thực" sẽ chỉ mất giao dịch cuối cùng). Tất nhiên, bạn có thể viết mã để làm cho nó xử lý việc này. Sau đó, bạn có thể viết mã cho tất cả những thứ khác. Và sau đó bạn nhận ra rằng bạn đã dành 6 tháng để viết một DB, mà bạn có thể đã sử dụng từ đầu, với rất ít nỗ lực.
Daniel B

200

Trong khi tôi đồng ý với tất cả những gì Robert nói, anh ấy đã không nói với bạn khi nào bạn nên sử dụng cơ sở dữ liệu thay vì chỉ lưu dữ liệu vào đĩa.

Vì vậy, hãy dùng điều này ngoài những gì Robert nói về khả năng mở rộng, độ tin cậy, khả năng chịu lỗi, v.v.

Để biết khi nào nên sử dụng RDBMS, đây là một số điểm cần xem xét:

  • Bạn có dữ liệu quan hệ, tức là bạn có một khách hàng mua sản phẩm của bạn và những sản phẩm đó có nhà cung cấp và nhà sản xuất
  • Bạn có lượng dữ liệu lớn và bạn cần nhanh chóng xác định được thông tin liên quan
  • Bạn cần bắt đầu lo lắng về các vấn đề trước đó được xác định: khả năng mở rộng, độ tin cậy, tuân thủ ACID
  • Bạn cần sử dụng các công cụ báo cáo hoặc thông minh để giải quyết các vấn đề kinh doanh

Khi nào nên sử dụng NoQuery

  • Bạn có rất nhiều dữ liệu cần được lưu trữ mà không có cấu trúc
  • Khả năng mở rộng và tốc độ
  • Nói chung, bạn không cần xác định lược đồ của mình trước, vì vậy nếu bạn có yêu cầu thay đổi thì đây có thể là một điểm tốt

Cuối cùng, khi nào nên sử dụng tập tin

  • Bạn có dữ liệu phi cấu trúc với số lượng hợp lý mà hệ thống tệp có thể xử lý
  • Bạn không quan tâm đến cấu trúc, các mối quan hệ
  • Bạn không quan tâm đến khả năng mở rộng hoặc độ tin cậy (mặc dù điều này có thể được thực hiện, tùy thuộc vào hệ thống tệp)
  • Bạn không muốn hoặc không thể đối phó với chi phí cơ sở dữ liệu sẽ thêm
  • Bạn đang xử lý dữ liệu nhị phân có cấu trúc thuộc hệ thống tệp, ví dụ: hình ảnh, tệp PDF, tài liệu, v.v.

14
+1, tôi nghĩ điều quan trọng là bạn đã chỉ ra rằng có những lúc tệp thực sự phù hợp để lưu trữ.
GrandmasterB

15
Bạn có thể thêm một ví dụ khác vào danh sách thứ ba của mình: Khi dữ liệu thực sự các tệp, ví dụ như hình ảnh được tải lên, tài liệu pdf, v.v. Điều này có vẻ hiển nhiên nhưng tôi đã thấy các trường hợp hình ảnh được lưu trữ trong một cơ sở dữ liệu không có lý do chính đáng nào.
Goran Jovic

5
Chà, không bao giờ có bất kỳ đề cập rõ ràng nào về việc nó là một ứng dụng web nhưng tôi đã suy luận từ nhận xét JSON. Tuy nhiên, đôi khi một số thứ sẽ chỉ được sử dụng bởi một vài người và bạn có thể biện minh cho phạm vi của ứng dụng để không lo lắng về khả năng mở rộng và độ tin cậy. Ý tôi là, không phải lo lắng về những thứ như phân cụm và dư thừa.
Sam

8
@GoranJovic đôi khi nó có ý nghĩa. Lưu trữ hơn 10.000 hình ảnh trong một thư mục và một số hệ thống tập tin sẽ ngừng hoạt động - một DB có thể dễ dàng hơn so với sơ đồ phân vùng thư mục con thủ công.
Martin Beckett

2
@MartinBeckett: hệ thống tập tin nào trong thập kỷ qua không?
Eamon Nerbonne

55

Một điều mà dường như không ai đề cập đến là lập chỉ mục hồ sơ. Cách tiếp cận của bạn hiện tại vẫn ổn và tôi cho rằng bạn có một bộ dữ liệu rất nhỏ và rất ít người truy cập nó.

Khi bạn trở nên phức tạp hơn, bạn thực sự đang tạo một cơ sở dữ liệu. Bất cứ điều gì bạn muốn gọi nó, cơ sở dữ liệu chỉ là một tập hợp các bản ghi được lưu trữ vào đĩa. Cho dù bạn đang tạo tệp, hay MySQL , SQLite hay bất cứ thứ gì đang tạo (các) tệp, cả hai đều là cơ sở dữ liệu.

Thứ bạn thiếu là chức năng phức tạp đã được tích hợp vào hệ thống cơ sở dữ liệu để giúp chúng dễ sử dụng hơn.

Điều chính mà lò xo để tâm là lập chỉ mục. OK, vì vậy bạn có thể lưu trữ 10 hoặc 20 hoặc thậm chí 100 hoặc 1000 bản ghi trong một mảng được tuần tự hóa hoặc chuỗi JSON và kéo nó ra khỏi tệp của bạn và lặp lại tương đối nhanh chóng.

Bây giờ, hãy tưởng tượng bạn có 10.000, 100.000 hoặc thậm chí 1.000.000 hồ sơ. Khi ai đó cố gắng đăng nhập, bạn sẽ phải mở một tệp có dung lượng lớn vài trăm megabyte, tải nó vào bộ nhớ trong chương trình của bạn, lấy ra một mảng thông tin có kích thước tương tự và sau đó lặp lại hàng trăm nghìn bản ghi chỉ để tìm một bản ghi bạn muốn truy cập

Một cơ sở dữ liệu phù hợp sẽ cho phép bạn thiết lập các chỉ mục trên các trường nhất định trong các bản ghi cho phép bạn truy vấn cơ sở dữ liệu và nhận được phản hồi rất nhanh, ngay cả với các tập dữ liệu khổng lồ. Kết hợp điều đó với một cái gì đó như Memcached hoặc thậm chí là hệ thống bộ nhớ đệm tại nhà (ví dụ: lưu trữ kết quả tìm kiếm trong một bảng riêng trong 10 phút và tải các kết quả đó trong trường hợp người khác tìm kiếm cùng một thứ ngay sau đó) và bạn sẽ có các truy vấn nhanh, một cái gì đó bạn sẽ không nhận được với một tập dữ liệu lớn như vậy khi bạn đọc / ghi thủ công vào các tệp.

Một điều khác liên quan đến việc lập chỉ mục là chuyển thông tin. Như tôi đã nói ở trên, khi bạn có các tệp hàng trăm hoặc hàng nghìn megabyte, bạn phải tải tất cả thông tin đó vào bộ nhớ, lặp lại thủ công (có thể trên cùng một luồng) và sau đó thao tác dữ liệu của bạn.

Với một hệ thống cơ sở dữ liệu, nó sẽ chạy trên (các) luồng riêng hoặc thậm chí trên máy chủ của chính nó. Tất cả những gì được truyền giữa chương trình của bạn và máy chủ cơ sở dữ liệu là một truy vấn SQL và tất cả những gì được truyền trở lại là dữ liệu bạn muốn truy cập. Bạn không tải toàn bộ dữ liệu vào bộ nhớ - tất cả những gì bạn gửi và nhận là một phần rất nhỏ trong tổng số dữ liệu của bạn.


1
1. Xin đừng bao giờ tải tất cả thông tin người dùng của bạn vào mã phía khách hàng! (Tôi chắc chắn đó chỉ là một ví dụ) 2. Tải nó ở vị trí đầu tiên từ tệp 100 MB lớn sẽ mất một lúc. 3. Ví dụ của bạn là chính xác, tuy nhiên, giả sử rằng bạn sẽ chỉ tìm kiếm theo tên người dùng. Điều gì xảy ra nếu bạn muốn lưu trữ nhiều dữ liệu hơn về người dùng? vd: Tuổi. Bây giờ bạn muốn tìm kiếm tất cả người dùng trong độ tuổi từ 20-30. Hoặc thậm chí đơn giản hơn, tìm người dùng theo địa chỉ khi json của bạn trông như thế này: {login: {pass: pass, add1: "123 sasd", city: "Bất cứ nơi nào"}}.
Thomas Clayson

2
Điểm cuối cùng của bạn có khả năng đúng, nhưng sau đó tôi có thể làm việc từ dữ liệu cũ - cụ thể, nếu tôi mở chương trình của bạn, tải cơ sở dữ liệu hiện tại sau đó 5 phút sau có người khác đăng nhập và chỉnh sửa một cái gì đó, cơ sở dữ liệu của tôi bây giờ là phiên bản mới hơn cho đến khi tôi thoát khỏi chương trình và bắt đầu lại. Nếu sau đó tôi chỉnh sửa cơ sở dữ liệu của mình và lưu lại, tôi sẽ ghi đè mọi thay đổi mà người dùng khác đã thực hiện. Khi bạn có cơ sở dữ liệu người dùng, đây có thể là bất cứ điều gì từ việc thay đổi mật khẩu của bạn. Nếu hai người dùng thay đổi mật khẩu của họ trong mỗi phiên khác thì một người dùng sẽ bị thay đổi.
Thomas Clayson

4
Tôi đã học được rất nhiều sau khi tìm kiếm một số điều về lập chỉ mục. Nó đã thực sự khai sáng. Cơ sở dữ liệu có ý nghĩa hơn một chút bây giờ. Vẫn còn một số điều tôi không hiểu, nhưng đó là một tiến bộ lớn. Cảm ơn câu trả lời đó!
MaiaVictor

4
Về chỉ số, không, cơ sở dữ liệu không lập chỉ mục mọi thứ tự động. Chỉ có một vài điều được tự động lập chỉ mục trong khi phần còn lại yêu cầu rõ ràng "vui lòng thực hiện lập chỉ mục này". Và các chỉ số giảm tìm kiếm theo thời gian logarit, O (log (n)) chậm hơn một chút so với hằng số.
Hoàng đế Orionii

1
Lo lắng về sự khác biệt giữa triển khai dựa trên băm và dựa trên b-cây là tối ưu hóa sớm. Nếu dữ liệu nằm trong chỉ mục, nó vẫn sẽ nhanh hơn hàng chục lần so với việc đọc nó ra khỏi đĩa.
SilverbackNet

14

Khi bạn có dữ liệu đơn giản, như một danh sách những điều bạn mô tả trong các nhận xét về câu hỏi của bạn, thì cơ sở dữ liệu SQL sẽ không cung cấp cho bạn nhiều. Rất nhiều người vẫn sử dụng chúng, bởi vì họ biết dữ liệu của họ có thể trở nên phức tạp hơn theo thời gian và có rất nhiều thư viện làm việc với cơ sở dữ liệu tầm thường.

Nhưng ngay cả với một danh sách đơn giản mà bạn tải, giữ trong bộ nhớ, sau đó viết khi cần, có thể gặp phải một số vấn đề:

Việc chấm dứt chương trình bất thường có thể làm mất dữ liệu hoặc trong khi ghi dữ liệu vào đĩa bị lỗi và cuối cùng bạn có thể giết toàn bộ tệp. Bạn có thể cuộn các cơ chế của riêng mình để xử lý việc này, nhưng cơ sở dữ liệu xử lý việc này cho bạn bằng cách sử dụng các kỹ thuật đã được chứng minh bằng trận chiến.

Nếu dữ liệu của bạn bắt đầu phát triển quá lớn và cập nhật quá thường xuyên, việc tuần tự hóa tất cả dữ liệu và lưu trữ của bạn sẽ là một nguồn lực lớn và làm chậm mọi thứ. Bạn sẽ phải bắt đầu tìm cách phân vùng mọi thứ, vì vậy nó sẽ không quá đắt. Cơ sở dữ liệu được tối ưu hóa để chỉ lưu những thứ thay đổi vào đĩa theo cách chịu lỗi. Ngoài ra chúng được thiết kế, vì vậy bạn có thể nhanh chóng tải các bit dữ liệu bạn cần tại bất kỳ thời điểm nào.

Ngoài ra, bạn không phải sử dụng cơ sở dữ liệu SQL. Bạn có thể sử dụng "cơ sở dữ liệu" NoQuery mà nhiều người làm, chỉ cần sử dụng JSON để lưu trữ dữ liệu. Nhưng nó được thực hiện theo cách chịu lỗi và theo cách mà dữ liệu có thể phân chia thông minh, truy vấn và phân chia thông minh trên nhiều máy tính.

Ngoài ra, một số người trộn lẫn mọi thứ. Họ có thể sử dụng kho lưu trữ dữ liệu NoQuery như Redis để lưu trữ thông tin đăng nhập. Sau đó sử dụng cơ sở dữ liệu quan hệ để lưu trữ dữ liệu phức tạp hơn, nơi họ cần thực hiện các truy vấn thú vị hơn.


12

Tôi thấy rất nhiều câu trả lời tập trung vào vấn đề đồng thời và độ tin cậy. Cơ sở dữ liệu cung cấp các lợi ích khác bên cạnh đồng thời, độ tin cậy và hiệu suất. Chúng cho phép không bận tâm đến cách các byte và ký tự được biểu diễn trong bộ nhớ. Nói cách khác, cơ sở dữ liệu cho phép lập trình viên tập trung vào "cái gì" hơn là "làm thế nào".

Một trong những câu trả lời đề cập đến các truy vấn. "Hỏi cơ sở dữ liệu SQL một câu hỏi" có tỷ lệ phù hợp với độ phức tạp của câu hỏi. Khi mã phát triển trong quá trình phát triển, các truy vấn đơn giản như "tìm nạp tất cả" có thể dễ dàng mở rộng thành "tìm nạp tất cả trong đó property1 bằng giá trị này và sau đó sắp xếp theo property2" mà không khiến nhà lập trình lo ngại để tối ưu hóa cấu trúc dữ liệu cho truy vấn đó. Hiệu suất của hầu hết các truy vấn có thể được tăng tốc bằng cách tạo chỉ mục cho một thuộc tính nhất định.

Lợi ích khác là quan hệ. Với các truy vấn, dữ liệu tham chiếu chéo từ các bộ dữ liệu khác nhau sẽ có các vòng lặp lồng nhau. Ví dụ: tìm kiếm tất cả các bài đăng trên diễn đàn từ người dùng có ít hơn 3 bài đăng trong hệ thống nơi người dùng và bài đăng là các bộ dữ liệu khác nhau (hoặc bảng DB hoặc đối tượng JSON) có thể được thực hiện bằng một truy vấn duy nhất mà không làm mất khả năng đọc.

Nói chung, cơ sở dữ liệu SQL sẽ tốt hơn các mảng đơn giản nếu khối lượng dữ liệu có thể lớn (giả sử hơn 1000 đối tượng), truy cập dữ liệu trong các phần không quan trọng và khác nhau của mã truy cập vào các tập hợp con khác nhau của dữ liệu.


Tôi hơi lúng túng về ý tưởng rằng bạn có thể bỏ qua cách thức công cụ được thể hiện. Trong khi bạn có thể bỏ qua điều này, nếu bạn làm, và đặc biệt. nếu bạn viết một truy vấn phức tạp hơn một chút, rất có thể ứng dụng của bạn không thể mở rộng được nữa. "Thêm chỉ mục" không phải lúc nào cũng có thể - bạn đã viết thư để tranh luận và đơn giản là nó không giúp ích nhiều cho các truy vấn có độ phức tạp kéo dài nhiều bảng. Khi các chỉ mục là cần thiết , ngụ ý rằng bạn đã mất lợi ích của khả năng truy vấn tương tác vì chỉ các truy vấn có cấu trúc cụ thể mới có thể trả lời được trong thời gian hợp lý.
Eamon Nerbonne

12

TLD

Có vẻ như bạn đã đưa ra một quyết định kỹ thuật lưu trữ dữ liệu ngắn hạn về cơ bản cho ứng dụng của mình - bạn đã chọn viết một công cụ quản lý cửa hàng dữ liệu tùy chỉnh.

Bạn đang ngồi liên tục, với các tùy chọn để di chuyển theo một trong hai hướng.

Về lâu dài, bạn sẽ có khả năng (gần như, nhưng không chắc chắn 100%) thấy mình gặp rắc rối và có thể tốt hơn để thay đổi sang sử dụng các giải pháp lưu trữ dữ liệu hiện có. Có những vấn đề hiệu suất cụ thể, rất phổ biến, có thể dự đoán được, bạn sẽ buộc phải giải quyết, và tốt hơn hết là bạn nên sử dụng các công cụ hiện có thay vì tự lăn.


Có vẻ như bạn đã viết một cơ sở dữ liệu mục đích tùy chỉnh (nhỏ), được ứng dụng của bạn tích hợp và sử dụng trực tiếp. Tôi giả sử bạn đang dựa vào một hệ điều hành và hệ thống tệp để quản lý việc đọc và đọc đĩa thực tế và coi sự kết hợp này như một kho lưu trữ dữ liệu.

Khi nào làm những gì bạn đã làm

Bạn đang ngồi ở một điểm ngọt để lưu trữ dữ liệu. Một hệ thống lưu trữ dữ liệu hệ điều hành và tệp rất tiện lợi, dễ truy cập và đa nền tảng di động. Sự kết hợp đã tồn tại quá lâu, mà bạn chắc chắn sẽ được hỗ trợ và chạy ứng dụng của bạn, trên hầu hết mọi cấu hình triển khai tiêu chuẩn.

Đây cũng là một sự kết hợp dễ dàng để viết mã cho - API khá đơn giản và cơ bản và phải mất tương đối ít dòng mã để làm cho nó hoạt động.

Nói chung, thật lý tưởng để làm những gì bạn đã làm khi:

  • Tạo mẫu ý tưởng mới
  • Xây dựng các ứng dụng rất khó có khả năng cần mở rộng, hiệu suất khôn ngoan
  • Bị hạn chế bởi các trường hợp bất thường, chẳng hạn như thiếu tài nguyên để cài đặt cơ sở dữ liệu

Lựa chọn thay thế

Bạn đang tiếp tục các tùy chọn và có hai "hướng" bạn có thể đi từ đây, những gì tôi nghĩ là "xuống" và "lên":

Xuống

Đây là tùy chọn ít khả năng nhất để áp dụng, nhưng nó ở đây vì mục đích hoàn chỉnh:

Bạn có thể, nếu bạn muốn, đi xuống , nghĩa là bỏ qua hệ điều hành và hệ thống tập tin hoàn toàn và thực sự viết và đọc trực tiếp từ đĩa. Lựa chọn này thường chỉ phù hợp trong trường hợp cần hiệu quả cực cao - ví dụ, nghĩ về một thiết bị máy nghe nhạc MP3 tối thiểu / nhỏ , không có đủ RAM cho một hệ điều hành đầy đủ chức năng, hoặc một cái gì đó như Wayback Machine , đòi hỏi khối lượng cực kỳ hiệu quả hoạt động ghi dữ liệu (hầu hết các cửa hàng dữ liệu đánh đổi việc ghi chậm hơn để đọc nhanh hơn, vì đó là trường hợp sử dụng phổ biến hơn nhiều cho hầu hết các ứng dụng).

Lên

Có một số loại phụ ở đây - mặc dù vậy, chúng không hoàn toàn độc quyền. Một số công cụ mở rộng cả hai, cung cấp một số chức năng trong mỗi công cụ, một số công cụ hoàn toàn có thể chuyển từ làm việc ở chế độ này sang chế độ khác và một số công cụ có thể được xếp chồng lên nhau, cung cấp chức năng khác nhau cho các phần khác nhau của ứng dụng.

Lưu trữ dữ liệu mạnh hơn

Bạn có thể thấy mình cần lưu trữ khối lượng dữ liệu cao hơn và cao hơn, trong khi vẫn dựa vào ứng dụng của riêng bạn để quản lý độ phức tạp thao tác dữ liệu. Toàn bộ các cửa hàng khóa-giá trị có sẵn cho bạn, với nhiều mức hỗ trợ khác nhau cho các chức năng liên quan. Các công cụ NoQuery rơi vào danh mục này, cũng như các công cụ khác.

Đây là đường dẫn rõ ràng để mở rộng quy mô khi phần sau mô tả ứng dụng của bạn:

  • Nó là phụ thuộc đọc nặng bất thường
  • Bạn có thể giao dịch với hiệu suất cao hơn để đảm bảo tính nhất quán (ngắn hạn) thấp hơn (nhiều ưu đãi mang lại "tính nhất quán cuối cùng").
  • Là "trực tiếp" quản lý hầu hết các thao tác dữ liệu và thiếu tính nhất quán (trong thực tế, ban đầu bạn có thể sẽ sử dụng công cụ của bên thứ ba, mặc dù cuối cùng bạn sẽ đưa ứng dụng này vào ứng dụng của bạn hoặc vào lớp trung gian bằng văn bản tùy chỉnh) .
  • Bạn đang tìm cách mở rộng quy mô số lượng dữ liệu bạn đang lưu trữ và / hoặc khả năng tìm kiếm thông qua dữ liệu đó với các yêu cầu thao tác dữ liệu "tương đối đơn giản".

Có một số phòng ngọ nguậy ở đây - bạn có thể buộc tính nhất quán đọc tốt hơn, để đọc chậm hơn. Các công cụ và tùy chọn khác nhau cung cấp apis thao tác dữ liệu, lập chỉ mục và các tùy chọn khác, có thể ít nhiều phù hợp để dễ dàng viết ứng dụng cụ thể của bạn. Vì vậy, nếu các điểm trên gần như mô tả hoàn toàn ứng dụng của bạn, bạn có thể "đủ gần" để làm việc với giải pháp lưu trữ dữ liệu mạnh hơn.

Các ví dụ nổi tiếng: CouchDB , MongoDB , Redis , các giải pháp lưu trữ đám mây như Azure của Microsoft , Kho dữ liệu ứng dụng của Google và ECE của Amazon.

Công cụ thao tác dữ liệu phức tạp hơn

Nhóm ứng dụng lưu trữ dữ liệu "SQL", cũng như một loạt các ứng dụng khác, được mô tả tốt hơn như các công cụ thao tác dữ liệu, hơn là các công cụ lưu trữ thuần túy. Chúng cung cấp một loạt các chức năng bổ sung, ngoài việc lưu trữ dữ liệu và thường vượt ra ngoài những gì có sẵn trong kho lưu trữ khóa-giá trị của mọi thứ. Bạn sẽ muốn đi theo con đường này khi:

  • Bạn hoàn toàn phải có tính nhất quán khi đọc, ngay cả khi điều đó có nghĩa là bạn sẽ đạt được thành tích.
  • Bạn đang tìm cách thực hiện hiệu quả thao tác dữ liệu rất phức tạp - hãy nghĩ đến các hoạt động THAM GIA và CẬP NHẬT rất phức tạp, các khối dữ liệu và cắt, v.v ...
  • Bạn ổn với việc giảm bớt độ cứng cho hiệu năng (nghĩ rằng các định dạng lưu trữ dữ liệu cố định, bị ép buộc, chẳng hạn như bảng, không thể dễ dàng và / hoặc thay đổi hiệu quả).
  • Bạn có các tài nguyên để đối phó với một bộ công cụ và giao diện phức tạp hơn gấp nhiều lần.

Đây là cách suy nghĩ "truyền thống" hơn về cơ sở dữ liệu hoặc lưu trữ dữ liệu và đã tồn tại lâu hơn nhiều - vì vậy có rất nhiều thứ có sẵn ở đây và thường có rất nhiều vấn đề phức tạp để giải quyết. Mặc dù có thể cần một số kiến ​​thức và kiến ​​thức chuyên môn và xây dựng các giải pháp đơn giản / tránh nhiều sự phức tạp - rất có thể bạn sẽ sử dụng các công cụ và thư viện của bên thứ ba để quản lý hầu hết các giải pháp đó cho bạn.

Các ví dụ nổi tiếng là MySQL , SQL Server , Cơ sở dữ liệu của Oracle và DB2 .

Thuê ngoài công việc

Có một số công cụ và thư viện của bên thứ ba hiện đại, tự xen kẽ giữa các công cụ lưu trữ dữ liệu và ứng dụng của bạn, để giúp bạn quản lý sự phức tạp.

Ban đầu, họ cố gắng lấy đi hầu hết hoặc tất cả các công việc quản lý và thao túng các cửa hàng dữ liệu, và, lý tưởng nhất, cho phép bạn thực hiện chuyển đổi suôn sẻ thành phức tạp chỉ khi và nếu cần. Đây là một lĩnh vực hoạt động của tinh thần kinh doanh và nghiên cứu, với một vài kết quả gần đây có thể truy cập ngay lập tức và có thể sử dụng được.

Các ví dụ nổi tiếng là các công cụ MVC ( Django , Yii ), Ruby on RailsDatomic . Thật khó để công bằng ở đây vì có hàng tá công cụ và thư viện hoạt động như các trình bao bọc xung quanh API của các cửa hàng dữ liệu khác nhau.


Tái bút: nếu bạn thích video hơn văn bản, bạn có thể muốn xem một số video liên quan đến cơ sở dữ liệu của Rich Hickey; anh ấy làm tốt công việc làm sáng tỏ hầu hết những suy nghĩ đi vào việc lựa chọn, thiết kế và sử dụng một kho lưu trữ dữ liệu.


11

Một hệ thống tệp phù hợp với mô tả của cơ sở dữ liệu NoQuery, vì vậy tôi nói rằng bạn chắc chắn nên cân nhắc sử dụng điều đó khi quyết định cách lưu trữ dữ liệu của mình và không bỏ qua việc ủng hộ RDBMS, như một số câu trả lời dường như gợi ý ở đây.

Một vấn đề với các hệ thống tệp (và NoQuery nói chung) là xử lý các mối quan hệ giữa dữ liệu. Nếu đó không phải là trình chặn chính ở đây, thì bây giờ tôi sẽ bỏ qua RDBMS. Cũng nhớ các mặt tích cực của việc sử dụng một hệ thống tệp làm lưu trữ:

  • Không quản trị
  • Độ phức tạp thấp, dễ thiết lập
  • Hoạt động với mọi hệ điều hành, ngôn ngữ, nền tảng, thư viện, v.v.
  • Chỉ có cài đặt cấu hình là thư mục
  • Tầm thường để kiểm tra
  • Tầm thường để kiểm tra với các công cụ hiện có, sao lưu, sửa đổi, v.v.
  • Đặc tính hiệu năng tốt và được điều chỉnh tốt bởi hệ điều hành
  • Bất kỳ nhà phát triển nào cũng dễ hiểu
  • Không phụ thuộc, không có trình điều khiển thêm
  • Mô hình bảo mật là tầm thường để hiểu và là một phần cơ bản của hệ điều hành
  • Dữ liệu không thể truy cập được từ bên ngoài

( nguồn )


10

Hệ thống tập tin là một loại cơ sở dữ liệu. Có thể không phải là một RDBMS như mọi người khác đang nói, nhưng chắc chắn là một DB theo nghĩa chặt chẽ nhất. Bạn đang cung cấp khóa (tên tệp) để tra cứu dữ liệu (nội dung tệp), có lưu trữ trừu tượng và API mà chương trình của bạn giao tiếp.

Vì vậy, bạn đang sử dụng một cơ sở dữ liệu. Các bài viết khác có thể tranh luận về những ưu điểm của các loại cơ sở dữ liệu khác nhau ...


1
cơ sở dữ liệu và lưu trữ thực sự không thể được sử dụng thay thế cho nhau. Cơ sở dữ liệu là một loại lưu trữ, nhưng một hệ thống tệp chắc chắn không phải là một loại cơ sở dữ liệu
Gaz_Edge 15/03/13

3
"Storage" là nơi giữ bit và byte. Một cơ sở dữ liệu không nhất thiết phải sử dụng các tệp trên một hệ thống tệp. Một hệ thống tệp chắc chắn là một loại cơ sở dữ liệu theo nghĩa chặt chẽ nhất của thuật ngữ này.
Chris S

6
Đối với ai đó đang tranh luận rằng không có sử dụng trong cơ sở dữ liệu khi họ thay thế là sử dụng cơ sở dữ liệu ; Đúng. Có vẻ hữu ích để giải thích cho họ rằng lập luận của họ dựa trên một quan niệm định trước là sai. Một khi họ hiểu rõ hơn về tình hình ban đầu của mình, chúng tôi có thể giúp họ tiến lên phía trước với sự hiểu biết đầy đủ hơn về các công nghệ có sẵn. Các hệ thống tệp là cơ sở dữ liệu phân cấp, có lý do chính đáng cho các hệ thống cơ sở dữ liệu đối tượng và quan hệ đã thay thế chúng như lưu trữ / truy xuất dữ liệu nhanh hơn, được tổ chức tốt hơn và hiệu quả hơn.
Chris S

2
@Gaz_Edge Dữ liệu đã có trong một "cơ sở dữ liệu" không hiệu quả bằng cách được lưu trữ trong một loạt các tệp có cấu trúc và nội dung được quản lý bởi ứng dụng của OP. Cố gắng để OP hiểu và chấp nhận đó là bước đầu tiên hữu ích để khiến họ hiểu trường hợp sử dụng cho hệ thống cơ sở dữ liệu "thực"; một khi họ hiểu rằng "cơ sở dữ liệu" nào đó đang xảy ra dù sao đi nữa, sẽ dễ dàng hơn để bắt đầu nói về nơi một dịch vụ được cấu trúc và quản lý đúng sẽ hiệu quả hơn là để ứng dụng tự làm việc của mình. Tôi muốn đề nghị câu trả lời này có ích, rất nhiều như vậy.
Rob Moir

8

Cần có cơ sở dữ liệu nếu bạn có nhiều quy trình (người dùng / máy chủ) sửa đổi dữ liệu. Sau đó, cơ sở dữ liệu phục vụ để ngăn chặn chúng ghi đè lên những thay đổi khác.

Bạn cũng cần một cơ sở dữ liệu khi dữ liệu của bạn lớn hơn bộ nhớ. Ngày nay với bộ nhớ chúng ta có sẵn, điều này thực sự làm cho việc sử dụng cơ sở dữ liệu trong nhiều ứng dụng trở nên lỗi thời.

Cách tiếp cận của bạn chắc chắn tốt hơn so với vô nghĩa của "cơ sở dữ liệu trong bộ nhớ". Đó thực chất là cách tiếp cận của bạn, nhưng với rất nhiều chi phí được thêm vào.


Thành thật mà nói, tôi thích câu trả lời này và muốn nó là sự thật, nhưng tôi không chắc đó là trường hợp. Ví dụ, một số người dùng (và bạn) nêu lên mối quan tâm về bộ nhớ. Tất nhiên, nếu tôi lưu trữ dữ liệu trị giá GB, tôi không thể lưu giữ tất cả vào bộ nhớ. Nhưng nếu tôi chắc chắn dữ liệu sẽ không bao giờ lớn như vậy, tôi có nên sử dụng bộ nhớ không? Vâng, có những thứ khác nữa. Ví dụ: tôi đã tìm hiểu về các quan điểm gia tăng của CouchDB. Đó chắc chắn là một cái gì đó, khác với việc lập chỉ mục, sẽ KHÔNG tầm thường khi tự thực hiện và chắc chắn là một sự tăng tốc lớn khi bạn đang sử dụng mô hình xem,
MaiaVictor

mà tôi đoán tôi là Ví dụ: khi tôi chuyển đổi dữ liệu từ "danh sách người chơi" sang "xếp hạng", đây không phải là hoạt động giảm bản đồ. Khi tạo trò chơi hoặc trang web tương tác, hầu hết mọi thứ bạn trình bày là thao tác mapReduce từ dữ liệu cốt lõi của bạn! Vì vậy, có loại tối ưu hóa có thể thực sự mong muốn. Chà, tôi không biết liệu có bất cứ điều gì tôi đang nói tiếp tục không, nhưng điều đó có ý nghĩa. Học được rất nhiều ngày hôm nay và tôi thực sự thích các khái niệm NoQuery. Cảm ơn câu trả lời (:
MaiaVictor

7

Bạn nên luôn tự hỏi mình nếu một ứng dụng cụ thể cần RDBMS. Quá nhiều ứng dụng được xây dựng với quy trình thiết kế tự động đảm nhận tất cả các công cụ và khung cần thiết ngay từ đầu. Cơ sở dữ liệu quan hệ rất phổ biến và nhiều nhà phát triển đã làm việc trên các ứng dụng tương tự như trước đây, chúng được tự động đưa vào trước khi dự án bắt đầu. Nhiều dự án có thể thoát khỏi điều này, vì vậy đừng phán xét quá gay gắt.

Bạn đã bắt đầu dự án của bạn mà không cần một, và nó hoạt động. Nó dễ dàng hơn cho bạn để có được điều này và chạy mà không cần đợi cho đến khi bạn SQL. Chẳng có vấn đề gì với việc đấy cả.

Khi dự án này mở rộng và các yêu cầu trở nên phức tạp hơn, một số thứ sẽ trở nên khó xây dựng. Cho đến khi bạn nghiên cứu và thử nghiệm các phương pháp thay thế, làm thế nào để bạn biết cái nào tốt hơn? Bạn có thể hỏi các lập trình viên và nhổ qua ngọn lửa và 'nó phụ thuộc' để trả lời câu hỏi này. Khi bạn tìm hiểu nó, bạn có thể xem xét có bao nhiêu dòng mã bạn muốn viết bằng ngôn ngữ của mình để xử lý một số lợi ích của cơ sở dữ liệu. Tại một số điểm, bạn đang phát minh lại bánh xe.

Dễ là thường tương đối. Có một số khung có thể xây dựng một trang web và kết nối một biểu mẫu với bảng cơ sở dữ liệu mà không yêu cầu người dùng viết bất kỳ mã nào. Tôi đoán nếu bạn vật lộn với chuột, đây có thể là một vấn đề. Mọi người đều biết, điều này không thể mở rộng hoặc linh hoạt bởi vì chúa cấm bạn kết hợp chặt chẽ mọi thứ với GUI. Một người không lập trình chỉ xây dựng một nguyên mẫu; rất nhiều YAGNI được tìm thấy ở đây.

Nếu bạn muốn học ORM được điều khiển bằng ngôn ngữ bạn chọn thay vì học SQL, hãy thử, nhưng thử cài đặt, tạo bảng và lấy một số dữ liệu ra khỏi cơ sở dữ liệu phổ biến bằng SQL (Chọn * Từ; không công cụ suy nghĩ). Thật dễ dàng để làm. Đó là lý do tại sao ai đó tạo ra chúng ở nơi đầu tiên. Nó dường như không phải là một khoản đầu tư lớn như vậy để đưa ra quyết định sáng suốt. Bạn có thể có thể làm một bài kiểm tra hiệu suất là tốt.


Chỉ cần lưu ý, tôi thực sự đã sử dụng mysql trong nhiều năm khi tôi lưu trữ một "otserv". Đoán xem cái gì? Tất cả những gì nó mang lại là vấn đề. Mọi người có thể "nhân bản" các vật phẩm bằng một mánh khóe bẩn thỉu sau khi họ nhận ra nhân vật của mình đã được lưu khi họ đăng xuất nhưng không phải khi máy chủ gặp sự cố. Đây là một vấn đề nghiêm trọng đối với otservs. Và cộng đồng otserv là LỚN. Điều đó sẽ không xảy ra nếu họ chỉ lưu trữ dữ liệu trên bộ nhớ và tuần tự hóa nó theo định kỳ. Vì vậy, tôi đã tự sửa đổi nguồn, các tệp C ++ dài đó và bắt đầu lưu vào mysql theo định kỳ, thay vì khi các ký tự đăng xuất. Đoán xem cái gì? Đó là CHẬM!
MaiaVictor 15/03/13

Mysql đơn giản là không thể xử lý hoàn toàn trạng thái tiết kiệm cứ sau 2 phút. Rõ ràng là việc tiết kiệm đã xảy ra - toàn bộ máy chủ "tụt lại" trong một giây. Bây giờ tôi thực sự đánh giá cao nếu mọi người đăng ở đây đã có câu trả lời cho câu hỏi đó!
MaiaVictor 15/03/13

1
Đừng đánh giá RDBMS bằng những gì đã xảy ra với một ứng dụng có thể được mã hóa kém. Đặc biệt là khi các sửa đổi để hỗ trợ cơ sở dữ liệu được thực hiện bởi một người không có kinh nghiệm về cơ sở dữ liệu.
alroc 15/03/13

1
@Dokkat, tôi hy vọng rằng không ai đá dây nguồn giữa việc gửi tiền vào tài khoản ngân hàng của bạn và "định kỳ" ghi số dư tài khoản vào đĩa. Bạn đã mô tả một kiến ​​trúc mất dữ liệu được đảm bảo. Điều đó tốt cho một số ứng dụng, nhưng hầu hết các ứng dụng cơ sở dữ liệu cung cấp cho người dùng quyền lựa chọn. Bạn có thể chạy một nút cơ sở dữ liệu với các bản sao lưu và có nguy cơ mất dữ liệu hoặc sử dụng bản sao để loại bỏ mất dữ liệu nếu một nút đơn bị lỗi.
mikerobi

@Dokkat vì vậy bạn không sử dụng MySql hoặc bất kỳ DB kiểu "máy chủ" đầy đủ tính năng nào khác. Bạn sử dụng Sqlite (hoặc tương tự) và nó sẽ tồn tại trên đĩa mỗi lần, trong khi cung cấp cho bạn một DB được nhúng trong ứng dụng của bạn (vì vậy không cần cài đặt riêng) và vẫn cung cấp cho bạn quyền truy cập sql, tính toàn vẹn giao dịch và tính bền vững của đĩa.
gbjbaanb

6

Lưu dữ liệu vào đĩa IS ghi nó vào cơ sở dữ liệu, đặc biệt nếu bạn đặt từng đối tượng vào tệp riêng của mình với tên của tệp là chìa khóa của bản ghi. Và để giảm thiểu thời gian tra cứu để đọc tệp, hãy tạo các thư mục con dựa trên một vài ký tự đầu tiên của khóa.

Ví dụ: key = ghostwriter sẽ có trong g / ho / stwriter.json hoặc g / h / o / stwriter.json hoặc g / ho / ghostwriter.json hoặc g / h / o / ghostwriter.json. Chọn sơ đồ đặt tên của bạn dựa trên việc phân phối các khóa của bạn. Nếu chúng là số thứ tự thì 5/4/3 / 12345.json tốt hơn so với cách khác.

Đó là một cơ sở dữ liệu và nếu nó làm tất cả những gì bạn cần, thì hãy làm theo cách đó. Ngày nay, nó sẽ được gọi là cơ sở dữ liệu NoQuery như GDBM hoặc Berkeley db. Quá nhiều lựa chọn. Trước tiên hãy tìm ra những gì bạn cần, sau đó xây dựng thư viện giao diện để xử lý các chi tiết, có thể là giao diện get / set như memcached hoặc giao diện CRUD, sau đó bạn sẽ có thể trao đổi thư viện nếu bạn cần thay đổi định dạng cơ sở dữ liệu cho một với những đặc điểm khác nhau.

Lưu ý rằng một số cơ sở dữ liệu SQL như PostgreSQL và Apache Derby DB, sẽ cho phép bạn thực hiện các truy vấn SQL trên đầu trang của nhiều định dạng NoQuery bao gồm cả cơ sở dữ liệu nhà riêng của bạn. Không chắc chắn về MyBatis nhưng nó có thể tương tự.

Tránh cường điệu NoQuery. Đọc về các tính năng, kiểm tra hiệu suất và khả năng và sau đó chọn dựa trên mức độ phù hợp với nhu cầu ứng dụng của bạn.

http://www.hdfgroup.org/HDF5/ là một định dạng kho dữ liệu thú vị và được sử dụng rộng rãi mà mọi người thường không xem xét.


4

Ngay sau khi dữ liệu được cập nhật đồng thời, cách tiếp cận sử dụng cơ sở dữ liệu (cũng có thể là cơ sở dữ liệu trong bộ nhớ) có thể sẽ chính xác và hiệu quả hơn, đồng thời mã của bạn vẫn dễ dàng, vì đơn giản là bạn không có lo lắng về các cập nhật đồng thời, giao dịch, bộ đệm, I / O không đồng bộ và tất cả những thứ đó.


Sửa đổi đồng thời trong một quy trình sẽ hiệu quả hơn bằng cách sử dụng các khóa trong quá trình thay vì IPC cho một trình nền cơ sở dữ liệu có được một loạt các khóa. Nhưng có lẽ bạn đang nói về nhiều quá trình sửa đổi dữ liệu.
dhasenan 15/03/13

@dhasenan - Đây là một lợi thế khác của hệ thống cơ sở dữ liệu tốt. Bạn có được sự tương tranh và nó hoạt động trong mọi trường hợp: Đa luồng, đa tiến trình, nhiều máy khách trên các máy chủ khác nhau hoặc bất kỳ sự kết hợp nào của chúng. Chương trình đa luồng của bạn có thể "hiệu quả hơn" trong một số trường hợp nhất định, nhưng đơn giản là nó sẽ không mở rộng được.
Ingo

-5

Bạn cần một cơ sở dữ liệu để lưu trữ / truy xuất QAs giống như những gì chúng tôi đang đăng ở đây! Một tệp đơn giản không thể tổ chức dữ liệu liên quan đến các chủ đề khác nhau.


3
Không, "chủ đề" có thể là các thư mục và "bài đăng" trên trang web có thể là các tệp. Chắc chắn có thể chạy một trang web như thế này khỏi một hệ thống tập tin. Nó không hiệu quả: chậm và phức tạp để phát triển, chạy truy vấn, chèn dữ liệu mới, v.v.
Chris S

chậm + phức tạp = không thể?
joe

Chậm và phức tạp để xây dựng! = Chậm và phức tạp để hoạt động
joe

1
@joe, thực sự không đúng khi một tệp (có thể không phải là tệp "đơn giản", nhưng điều đó có nghĩa là gì?) không thể được sử dụng để sắp xếp dữ liệu liên quan đến các chủ đề khác nhau. Bạn có thể sử dụng JSON, như Dokkat gợi ý, hoặc XML hoặc các tệp bản ghi hỗn hợp như chúng tôi đã sử dụng để quay lại trong những ngày trước XML hoặc bất kỳ định dạng tệp nào bạn có thể mơ thấy. Tôi sẽ không đề xuất bất kỳ phương pháp tiếp cận nào trong hầu hết các kịch bản, nhưng điều đó không có nghĩa là chúng không thể được thực hiện.
John M Gant

@ John M Gant: hoàn toàn đồng ý với bạn, cơ sở dữ liệu không thể thay thế các tệp đơn (vì bạn không thích đơn giản) và ngược lại, vì lý do duy nhất là xe hơi không thể thay thế xe đạp. tôi nói được 3 ngôn ngữ "con người", và sự lựa chọn từ và từ vựng của tôi là lý do khiến tôi bị hiểu lầm ... tôi đoán
joe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.