Створення підключень до бази даних - Робіть це один раз або для кожного запиту?


101

На даний момент я створюю підключення до бази даних під час першого завантаження моєї веб-сторінки. Потім я обробляю сторінку та запускаю будь-які запити проти цього з’єднання. Це найкращий спосіб зробити це чи я повинен створювати підключення до бази даних кожного разу, коли запускаю запит?

ps Мені більше сенсу створити 1 з'єднання та використовувати його, але я не знаю, чи це може спричинити якісь інші проблеми.

Я використовую C # (ASP.NET) з MSSQL.

Відповіді:


124

Якщо ви створюєте один за запитом / транзакцією, керувати "закриттям" з'єднань набагато простіше.

Я бачу, чому здоровий глузд наказує, що ви повинні відкривати його та використовувати його протягом усього часу, але ви зіткнетесь із проблемами зі скинутими з'єднаннями та багатопотоковою читанням. Отже, наступним вашим кроком буде відкриття пулу, скажімо, 50, підключень та зберегти їх усіма відкритими, дозволити їх різним процесам. І тоді ви дізнаєтесь, що саме це .NET Framework вже робить для вас .

Якщо ви відкриєте підключення, коли вам це потрібно, і розпоряджаєтесь ним, коли закінчите, це фактично не закриє з'єднання, воно просто поверне його до пулу з'єднань, щоб знову використовувати його.


Просто читав цю статтю, коли ви її опублікували :) Дякую.
webnoob

2
Веб-сторінка, до якої ви пов’язані, є специфічною для SQL Server. Чи забезпечує .NET також автоматичне об'єднання під час підключення до інших баз даних, наприклад - Oracle, Sqlite, MySql?
briddums

@briddums - Я думаю, що це залежить від роз'єму. .Net, наприклад, не забезпечує роз'єм MySql. Це написано та підтримується MySql. І хоча це працює, на мій досвід, попередня реалізація була далеко не вільною від помилок.
ZweiBlumen

1
@briddums: Залежить від складання постачальника. Я впевнений, що впровадження Microsoft Oracle та власне об'єднання Oracle підтримують з'єднання, оскільки я їх використовував. Я чув, що існує MySql, і я сподівався, що провайдери в Spring.NET підтримуватимуть об'єднання, але вам краще шукати або просити постачальника безпосередньо, ніж запитувати мене.
pdr

1
Слід знати, що відкриття, запуск запиту та розміщення з'єднання, навіть у циклі, однаково швидко, а іноді і швидше, ніж відкрити його один раз і циклічно запитувати. Завжди просто розпоряджайтеся. Це більш безпечно і швидше. Не турбуйтеся про накладні витрати на отримання з'єднання з басейну - це так банально.
smdrager

38

Найкраще практикувати це, щоб створити одне з'єднання за запитом - а у випадку відображення даних найкращою практикою є те, щоб запит вносив усі необхідні дані за один раз.

Довідкова інформація:

У .NET при виклику SqlConnection.Open()за замовчуванням завжди прозоро використовувати об'єднання з'єднань (див. "Використання з'єднання підключення за допомогою SQL Server" на MSDN). Таким чином, ви можете просто перехопити нове з'єднання за допомогою Open()та дзвонити, Close()коли закінчите, і .NET зробить правильно.

Зауважте, що без об'єднання з'єднань одне підключення на запит було б дуже поганою ідеєю, оскільки створення реальних підключень до бази даних може бути дуже дорогим (автентифікація, накладні витрати мережі тощо), а кількість одночасних відкритих з'єднань зазвичай дуже обмежена.


7
@webnoob - Оскільки .NET використовує об'єднання з'єднань, ні, це не так. Причина полягає в тому, що з'єднання можуть закриватися, перерозподілятися тощо - тому повторне використання з'єднання не є хорошою практикою.
Одід

11
-1 Відповідь є досить оманливою. Створення з'єднання за запитом - дуже погана ідея. Що ви, мабуть, маєте на увазі, це "отримати нове з'єднання для кожного запиту з пулу з'єднань", але це не те саме, що створення з'єднання.
sleske

1
@sleske - Чим це відрізняється від відповіді pdr?
Одід

3
@Oded: Ах, бачу. У .NET, виклик SqlConnection.Open()завжди буде прозоро використовувати об'єднання з'єднань. Отже, різниці між "відкрити з'єднання" та "відновити з'єднання з пулу" не існує. Моє непорозуміння. Я взяв на себе сміття змінити невелике пояснення до питання і взяв назад голосування.
sleske

2
@ eaglei22 - це, безумовно, має робити це (див. docs.microsoft.com/en-us/dotnet/framework/data/adonet/… ). Загалом, ви хочете повернути з'єднання до пулу якнайшвидше, хоча, якщо ви видаєте кілька запитів послідовно, можливо, буде краще використати з'єднання за вашими пропозиціями. Вам потрібно перевірити і побачити, який підхід для вас кращий (я не знаю, якими критеріями ви користуєтесь - перевіряйте обидва способи та бачите вплив на вибрані вами показники).
Одід

0

Пам'ятайте про все це в контексті екосистеми .Net.

Інколи розробники хочуть "оптимізувати" свій код для повторного використання об'єктів з'єднання. Зважаючи на контекст цього питання, це майже завжди є помилкою.

ADO.Net має функцію під назвою Пул з'єднання . Коли ви створюєте та відкриваєте новий об'єкт з'єднання, ви дійсно робите запит на з'єднання з пулу. Коли ви закриєте з'єднання, ви повернете його до пулу.

Важливо зрозуміти об'єкти, які ми використовуємо безпосередньо в коді: SqlConnection, MySqlConnection, OleDbConnectio тощо - це лише обгортки навколо реального базового з'єднання, яким керує ADO.Net, а реальні з'єднання ADO.Net набагато "важчі" та дорожчі з точки зору продуктивності. Саме такі основні об'єкти мають такі проблеми, як аутентифікація, транзит мережі, шифрування, і ті речі набагато переважають малу кількість пам'яті в об'єкті, який ви насправді бачите у власному коді.

При спробі повторно використовувати об’єкт підключення, ви порушуєте можливість ADO.Net ефективно керувати важливими базовими з'єднаннями. Ви отримуєте ефективність у дрібниці за рахунок значно більшої речі.

Повторне використання з'єднання через додаток або запит http також може змусити вас випадково серіалізувати щось, що інакше могло б працювати паралельно, і стати вузьким місцем продуктивності. Я бачив, як це відбувається в реальних програмах.

У випадку прикладу веб-сторінки тут, де ви принаймні зберігаєте лише невелике з'єднання протягом тривалості одного запиту / відповіді http, ви можете отримати ще більшу ефективність, оцінивши, які запити виконуються у вашому конвеєрі запитів, і спробуйте отримати їх можна зменшити до якомога менше окремих запитів до бази даних (підказка: ви можете подати більше одного запиту в одну рядок SQL та використовувати DataReader.NextResult()або перевіряти різні таблиці, DataSetщоб переходити між ними).

Іншими словами, замість того, щоб думати з точки зору повторного використання одного з'єднання для програми або http-запиту проти одного з'єднання на запит, продумайте терміни одного з'єднання кожного разу, коли ви звертаєтесь до бази даних ... кожну туру. Потім спробуйте мінімізувати кількість з'єднань, мінімізуючи кількість цих поїздок. Таким чином ви можете задовольнити обидві цілі.


Але це лише один вид оптимізації. Також є оптимізація програмного часу та отримання ефективного повторного використання коду. Розробники не хочуть знову і знову писати один і той же код котла, щоб отримати об'єкт підключення, відкритий і готовий до використання. Це не тільки нудно, це спосіб ввести помилки в програму.

Навіть тут, однак, краще мати одне з'єднання за запитом (або в обидва кінці). Існують і інші зразки, які можна використовувати, щоб уникнути повторного запису того ж кодового коду. Ось один приклад, який мені подобається, але є багато інших.


Я запізнююсь на цю вечірку, але я думаю, що ця відповідь охоплює деякі важливі моменти :)
Джоель Куехорн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.