2012-05-22 29 views
29

Tôi đã dành thời gian đọc các phương pháp hay nhất khác nhau cho cơ sở dữ liệu và cho SQLite cụ thể. Trong khi đọc tôi thấy tôi đã làm nhiều điều tôi không nên làm và khi cố gắng sửa chữa những vấn đề này tôi trở nên bối rối khi suy nghĩ về một số chi tiết tốt hơn về cách sử dụng SQLite với việc thực hiện ADO của nó.SQLite/C# Kết nối Pooling và chuẩn bị báo cáo Confusion

Sự nhầm lẫn của tôi bắt nguồn từ các báo cáo chuẩn bị và kết nối tổng hợp.

Khi đọc http://msdn.microsoft.com/en-us/library/ms971481.aspx Tôi thấy rằng các kết nối chỉ nên được mở cho một giao dịch. Khi giao dịch hoàn tất thì kết nối sẽ được đóng lại. Tôi không hiểu rõ lý do tại sao đây là trường hợp, nhưng tôi đã làm việc với giả định rằng tác giả biết rõ hơn sau đó I. Tôi hiểu rằng khi kết nối bị đóng, điều đó không có nghĩa là đã bị đóng. Nó chỉ đơn giản có nghĩa là nó đã được đưa trở lại vào hồ bơi.

Bây giờ, để cải thiện truy vấn và chèn của tôi, tôi đã đọc về cách sử dụng câu lệnh đã chuẩn bị. In SQLite, do prepared statements really improve performance?http://petesbloggerama.blogspot.com/2007/02/sqlite-adonet-prepared-statements.html cả hai dường như chỉ ra rằng khi thực hiện một truy vấn sẽ được thực hiện nhiều lần chuẩn bị báo cáo là con đường để đi. Tôi cũng đã đọc rằng một câu lệnh chuẩn bị cụ thể cho một kết nối và rằng khi kết nối được đóng, câu lệnh đã chuẩn bị bị mất.

Sự nhầm lẫn của tôi là điều này. Nếu tôi mở và đóng kết nối của tôi (có thể hoặc không có nghĩa là kết nối đang bị đóng do hồ bơi luồng) thì tôi sử dụng bao nhiêu từ một tuyên bố đã chuẩn bị? Tôi có thể hiểu rằng nếu tôi có 1000 đối tượng tôi cần lưu trong một giao dịch duy nhất thì câu lệnh chuẩn bị có thể giúp ích rất nhiều. Tuy nhiên tôi không tin rằng tôi sẽ thấy một lợi ích từ việc tiết kiệm một đối tượng duy nhất trong một giao dịch bởi vì một khi tôi đóng kết nối, câu lệnh đã được tạo ra từ đối tượng đầu tiên hiện đã bị mất. Đây có phải là một tuyên bố đúng không?

Sự nhầm lẫn của tôi được tiếp tục bởi thực tế là tôi tin rằng một câu lệnh chuẩn bị được liên kết với phạm vi đối tượng SQLiteCommand của tôi.

Nếu tôi tạo một SQLiteCommand đại diện cho một truy vấn mà tôi sẽ thực hiện thường xuyên, tôi có cần phải giữ cho SQLiteCommand đó trong bộ nhớ cho câu lệnh chuẩn bị để hoạt động không?

Nếu tôi tạo một SQLiteCommand mới với cùng một câu lệnh SQLite, nó có nhận ra rằng SQLiteCommand mới giống như trước đó và do đó có một câu lệnh chuẩn bị có thể được sử dụng không?

Nếu tôi giữ SQLiteCommand trong bộ nhớ và thay đổi thông số và kết nối khi tôi mở và đóng kết nối cho các giao dịch khác nhau, tôi có giữ nguyên câu lệnh chuẩn bị giữa các kết nối khác nhau không?

Tôi có nhiều khả năng sẽ suy nghĩ nhiều hơn vào thời điểm này nhưng tôi hy vọng bạn có thể giúp tôi hiểu rõ hơn cách những thứ này tương tác để tôi có thể nhận được nhiều lợi ích nhất từ ​​chúng.

+2

Tôi không thạo SQLite, nhưng liên quan đến lý do tại sao một người nên đóng kết nối càng sớm càng tốt, bạn gần như tự trả lời: Kết nối vật lý cơ bản không bị đóng, bạn chỉ trả lại kết nối với hồ bơi. Hàm ý là nó có thể được sử dụng bởi các chủ đề khác. Rõ ràng, nếu bạn treo vào một kết nối nhưng không thực sự sử dụng nó, điều đó sẽ hạn chế tối đa khả năng sử dụng. (Tương tự rõ ràng: nếu bạn đang ở trong một bối cảnh đơn luồng, kết nối tổng hợp không làm cho rất nhiều ý nghĩa, mặc dù nó là unlikley để làm tổn thương bạn nhiều.) –

Trả lời

0

Tôi không nắm bắt chính xác vấn đề cốt lõi là gì, nhưng nếu vấn đề là cách chèn câu lệnh chèn hàng loạt vào một giao dịch trong thời gian quá ít.

Đây là một lớp helper tôi thấy trước đây có thể giúp bạn:

SQLiteBulkInsertHelper.cs

Bạn có thể sử dụng nó như thế này:

SQLiteBulkInsertHelper ContactBlk = new SQLiteBulkInsertHelper("<SQLiteConnection>","<Table Name>"); 
ContactBlk.AllowBulkInsert = true; 
ContactBlk.AddParameter("<Column Name>", /*Column Data Type*/System.Data.DbType.Int64); 
ContactBlk.AddParameter("<Column Name>", /*Column Data Type*/System.Data.DbType.String); 
ContactBlk.Insert(new object[] {<First Column Value>,<Second Column Value>}); 
ContactBlk.Flush(); 

Hãy thử nếu bạn nhìn thấy nó như là một giải pháp cho vấn đề của bạn.

+0

Liên kết bạn đăng dường như bị hỏng. (Chrome tuyên bố vòng lặp chuyển hướng vô tận) –

+0

tất nhiên bạn có thể sử dụng dòng chèn trong vòng lặp và gọi các từ sau tuôn ra để giao dịch, liên kết trợ giúp lại: [SQLiteBulkInsertHelper.cs] (https://docs.google.com/open? id = 0B5-wcgU-Ku-eMDNlY1R3SzByV00) –

+0

OK, nhờ liên kết bạn đăng trong nhận xét có vẻ ổn, tôi cũng đã sửa nó trong bài đăng của bạn. –

15

Nó giúp nhớ rằng cả hai kết nối tổng hợp và chuẩn bị (biên dịch) báo cáo chỉ là công cụ có giới hạn của họ và không có cách tiếp cận có thể được bình đẳng phù hợp với tất cả các tình huống có thể. Với điều này trong tâm trí, hãy nhớ khi nào người ta có thể muốn sử dụng kết nối tổng hợp và báo cáo chuẩn bị.

Lý do có thể xảy ra để sử dụng kết nối tổng hợp

kết nối tổng hợp rất hữu ích khi kết nối được đắt tiền, ví dụ:

  • Phải mất thời gian đáng kể để thiết lập kết nối (kết nối mạng đến một SQL Máy chủ hoặc Oracle DB) và nó có lợi cho "cache" các kết nối mở trong một nỗ lực để cải thiện hiệu năng hệ thống.
  • Kết nối là bị giới hạn và chia sẻ trong một ứng dụng (kết nối từ ứng dụng web phân phối nhiều yêu cầu đồng thời) hoặc giữa các ứng dụng để chúng phải được phát hành càng sớm càng tốt để cho các khách hàng khác tiếp tục.

Lý do có thể xảy ra để sử dụng chuẩn bị phát biểu

báo cáo chuẩn bị đơn giản có nghĩa là để cải thiện hiệu suất truy vấn tái sử dụng bằng cách cắt giảm thời gian phân tích cú pháp.

SQLite: Lựa chọn tốt nhất là gì?

Câu trả lời tùy thuộc vào yêu cầu ứng dụng của bạn. Cá nhân, tôi không chắc chắn nếu kết nối SQLite tổng hợp là nhất thiết phải là một lựa chọn tốt. Nếu ứng dụng của bạn là đơn luồng, có thể tốt nhất là sử dụng một kết nối vĩnh viễn duy nhất cho DB SQLite, có thể nhanh hơn nhiều so với gộp và sẽ cho phép bạn sử dụng các câu lệnh đã chuẩn bị. Điều này khác với SQL Server nơi kết nối tổng hợp là một mặc định rất hợp lý.

Nếu các vấn đề về hiệu năng, bạn chắc chắn nên lập hồ sơ ứng dụng để xem liệu kết nối SQLite có mang lại lợi ích cho kịch bản của bạn hay không.

Câu hỏi dành riêng

Hầu hết các câu trả lời có liên quan đến hiện tại System.Data.SQLite cung cấp source.

Nếu tôi mở và đóng kết nối của tôi (mà có thể hoặc có thể không có nghĩa là kết nối đang được đóng cửa do các hồ bơi thread) sau đó bao nhiêu sử dụng tôi thực sự nhận được từ một tuyên bố chuẩn bị?

Nói chung, bạn nên xử lý kết nối sắp ra khỏi hồ bơi như mới, tức là bạn không nên mong đợi nhận được bất kỳ lợi ích nào từ các báo cáo được chuẩn bị trước đó. Câu lệnh sẽ được "tái chuẩn bị" trừ khi bạn giữ cả lệnh và kết nối.

Tuy nhiên tôi không tin rằng tôi sẽ thấy một lợi ích từ tiết kiệm một đối tượng duy nhất trong một giao dịch bởi vì một khi tôi đóng kết nối báo cáo kết quả chuẩn bị đã được tạo ra từ các đối tượng đầu tiên tại là mất.Đây có phải là một tuyên bố đúng không?

Đây là tuyên bố đúng.

Nếu tôi tạo ra một SQLiteCommand đại diện cho một truy vấn mà tôi sẽ thực hiện thường xuyên để tôi cần phải giữ SQLiteCommand rằng trong bộ nhớ cho các tuyên bố chuẩn bị để ở lại hoạt động?

Có, bạn cần giữ nó. SQLiteCommand giữ tham chiếu đến câu lệnh đã chuẩn bị.

Nếu tôi tạo ra một SQLiteCommand mới với tuyên bố SQLite cùng là nó nhận ra rằng SQLiteCommand mới là giống như trước và do đó có một tuyên bố chuẩn bị có thể được sử dụng?

Tôi không nghĩ rằng nó được hỗ trợ.

Nếu tôi giữ một SQLiteCommand trong bộ nhớ và thay đổi nó là thông số và kết nối như tôi mở và đóng kết nối cho giao dịch khác nhau tôi về cơ bản giữ một tuyên bố chuẩn bị sống giữa các kết nối khác nhau?

Nếu bạn thay đổi kết nối SQLiteCommand, tuyên bố sẽ được "chuẩn bị lại".

+0

Một lý do bổ sung rất quan trọng để sử dụng các câu lệnh đã chuẩn bị, đặc biệt là cho các chèn và cập nhật, là để ngăn chặn các cuộc tấn công SQL injection. Câu lệnh đã chuẩn bị đúng cách thoát khỏi giá trị được lưu trữ như trong cơ sở dữ liệu trong mọi trường hợp. –

Các vấn đề liên quan