2010-10-08 3 views
3

Для этого требуется немного фона. Я создаю веб-приложение (ASP.NET/VB.NET с бэкэнд SQL Server), которое будет принимать приложение для получения финансирования, и эта форма имеет контактные поля для трех человек. Поскольку информация одинакова для всех трех человек (имя, адрес электронной почты, телефон), я решил сохранить контактную информацию в таблице отдельно от приложений. В таблице приложений есть поле идентификатора для каждого из этих трех контактов, которое указывает на контакт в таблице контактов.Какова реальная стоимость транзакции SQL?

Однако, это представляет интересный вопрос/проблему при выполнении моих вещей CRUD. Единственные способы, которые я могу придумать для создания, обновления и извлечения информации для приложения и всех трех контактов в одной транзакции SQL, требуют очень сложных хранимых процедур. Другими словами, было бы намного проще (для меня) получить эту информацию через несколько транзакций. Однако, поскольку эта информация никогда не нужна независимо, я ВСЕГДА выполняю несколько транзакций для получения информации для одного приложения.

Так мои вопросы:

  1. Является ли это дизайн излишество? На одно приложение не будет больше трех человек, и ДОЛЖНО быть ровно три. Я слишком усложняю, удалив эту информацию в отдельную таблицу?
  2. Какова реальная стоимость выполнения нескольких транзакций SQL против написания сложных хранимых процедур и только одна транзакция?
  3. Вообще говоря, какова стоимость транзакции SQL для веб-приложения с использованием ADO.NET?

Спасибо за подшипник с этим длинным объяснением.

* РЕДАКТИРОВАНИЕ *

После прочтения некоторых из ваших ответов, по-видимому, я использую термин «сделки» неправильно. То, что я есть Фактически Любопытно, что это затраты на выполнение нескольких запросов в одном соединении, а также на выполнение одного запроса. Извините за недопонимание.

+0

Это не так, и я повторяю не «сложную хранимую процедуру». Если у вас несколько изменений в базе данных, которые являются единицей работы, вы должны использовать транзакцию, «стоимость» имеет только некоторые изменения и некоторые из них не были сделаны. –

ответ

8

Сделки необходимы для перемещения базы данных из одного согласованного состояния в другое согласованное состояние. «Согласованный» здесь применяется к представлению приложения базы данных. Типичным примером является денежный перевод между двумя учетными записями: вы должны дебетовать одну учетную запись и кредит другой учетной записи. Между этими двумя операциями база данных непоследовательна, есть некоторые деньги, которые «исчезли» (сумма, дебетованная с одной учетной записи, равна нигде). Но в конце транзакции база данных снова непротиворечива. Для выполнения этих двух операций необходима транзакция, чтобы защитить читателей от просмотра несогласованной базы данных и обеспечить согласованную базу данных в случае сбоя.

Вы говорите, что для обработки нескольких элементов в вашей логике в рамках одной транзакции вам требуются сложные процедуры. Это неверно, область транзакций ортогональна области запроса: клиент может начать транзакцию, выполнить 3 операции, вызвав 3 процедуры в 3 вызовах, а затем зафиксировать транзакцию. Это не требует, чтобы все операции выполнялись в одной хранимой процедуре.

Таким образом, транзакция должна быть не вызывает существенные накладные расходы. Фактически, процедура будет не обращать внимания на транзакции. Хорошо написанная процедура должна корректно вести себя при вызове внутри транзакции, а также при вызове без транзакции. См. Exception handling and nested transactions для шаблона процедур, которые ведут себя корректно при наличии транзакций и исключений.

В конце концов, что такое real Стоимость операции? Транзакция пишет данные (читать не нужны транзакции), и поэтому они блокируют строки, измененные. Обычно считывает блок при попытке прочитать эти заблокированные строки, а затем чем длиннее транзакция, тем дольше она блокирует строки и чем больше читает ее блокирует. Но есть очень простое решение: чтение моментальных снимков. Чтение снимков - действительно волшебная пыль пикселов, они позволяют приложениям идти вперед без помех заблокированными строками, потому что читатель всегда может прочитать версию строки до до обновления, которое блокирует строку. См. Using Row Versioning-based Isolation Levels.

Таким образом, вывод прост: транзакции не имеют стоимости. Просто потому, что нет альтернативы сделкам. Не проблема «X медленнее, чем Y», это проблема «X» - это только правильный вариант ».

Обновлено

После правки: стоимость ой наличие нескольких запросов против одного запросов могут быть значительными. Поездка на сервер (т. Е. Выдача запроса по открытому соединению) имеет фиксированную стоимость. Если вы совершаете многократные поездки, вы оплачиваете эту фиксированную стоимость по каждому запросу. Если вы делаете один запрос с несколькими вызовами процедур, эта фиксированная стоимость выплачивается только один раз. В очень горячих системах, эта разница измерима и имеет общую стоимость. Но я говорю о действительно горячих системах, как в тысячах запросов в секунду. Решение, как правило, не усложнять процедуры, но выдавать многократные вызовы процедур в одном запросе:

SqlCommand cmd = new SqlCommand(@" 
exec usp_firstProc @arg1, @arg2; 
exec usp_secondProc @arg2, @arg3; 
exec usp_thirdProc @arg1, @arg3;", connection); 
cmd.Parameters.Add("@arg1", someValue); 
... 
cmd.ExecuteNonQuery(); 

Но я должен сказать, что это решение на самом деле не требуется, если у вас есть действительно горячей нагрузки. В качестве правила обратной оболочки, для чего угодно менее 1000 запросов/сек, я бы рассмотрел преимущества четкого кода, чтобы перевесить преимущества производительности.

Одна вещь другая, хотя если у вас есть открыть новое соединение для каждого запроса. Рукопожатие для входа - действительно дорого, может быть измерено в сотни мс. Но решение тривиально: объединение пулов (включено по умолчанию в ADO.Net) и не отбрасывает соединения в приложении преждевременно, сохраняйте соединение и повторно используйте его до завершения всей единицы работы.

+0

+1 и принято! Это отличный ответ! Вы четко знаете свой материал :) – Ender

0

Вы используете здесь термин «транзакция». Я думаю, что вы имеете в виду простой запрос базы данных, помощник по транзакциям ACID.

Это, как трудно сказать. Пул соединений, включенный по умолчанию, предотвратит необходимость открытия трех/четырех отдельных подключений.

Вы бы, скорее всего, не нужно даже несколько запросов для получения данных, и может объединить эти две таблицы, чтобы получить его, например:

SELECT app.field1, app,field2, contact1.name, contact2.name, contact3.name 
FROM Applications AS app 
INNER JOIN Contacts AS contact1 ON app.contact1ID = contact1.id 
INNER JOIN Contacts AS contact2 ON app.contact2ID = contact2.id 
INNER JOIN Contacts AS contact3 ON app.contact3ID = contact3.id 

или что-то подобное, учитывая ваше положение (добавление новых полей в выбор списка из приложения, возврат большего количества данных из каждой таблицы контактов и т. д. Если таблицы индексируются правильно, поиск выполняется очень быстро и, вероятно, вообще не повлияет на производительность.

Если вы вставляете/обновляете данных, то да, вам понадобится несколько запросов для этого, но выбор данных может произойти в одном.

Конечно, другой вариант заключается в том, чтобы вернуть данные в исходную таблицу приложений, исключив необходимость во второй таблице. В этот момент никаких дополнительных объединений или чего-либо еще не требуется.

-1

Используйте 1 хранимую процедуру, чтобы сделать все, чтобы вам нужно было открыть только 1 соединение.

Каждая переменная в ваших веб-формы карты для параметра хранимой процедуры (в том числе и скрытых контактов и приложений ключи, которые вы по умолчанию 0 для новых приложений)

В процедуре, если запись ключи 0, процедура добавляет записи в базу данных и быстро извлекает ключи, используя scope_identity(). Если вы отправляете ненулевые ключи в процедуру, она обновляет запись. Затем процедура возвращает все данные обратно, все переменные хранимой процедуры, объявленные как выходные.

Затем вы можете обернуть процедуру внутри транзакции begin/end sql, так что это все или ничего.

+1

Я не понимаю - зачем нам приносить хранимые процедуры? –

+0

Потому что ответ плох. – TomTom

1
  1. Это не избыток. Это хорошая нормализация и хорошее применение принципа Don't-Repeat-Yourself. Требования системы могут измениться, и вам может понадобиться 2 или 4 контакта в будущем вместо 3.
  2. Вам не нужно выполнять сложные хранимые процедуры. Здесь вы не делаете ничего необычного. Вам вообще не нужны хранимые процедуры.
  3. Не знаю.

Когда вы говорите «транзакция», я думаю, вы просто имеете в виду «запрос». Когда я хотел, чтобы получить данные для одного приложения, я хотел бы использовать два отдельных, простые запросы:

SELECT * 
    FROM application 

и

SELECT * 
    FROM contact 

Это два отдельных запросов, но большое дело. Более важная часть - это создание базы данных таким образом, чтобы это имело смысл.

+0

Кроме того, когда вы вставляете эти записи, вы обязательно должны использовать транзакцию. Вы можете прочитать об этом здесь: http://jasonswett.net/why-you-should-use-database-transactions/ –

0

Пара мысли для вас ...

Если текущий дизайн две таблицы, первая таблица (applciation) как

ID, contact_id1, contact_id2, contact_id3, otherinfo

второй таблицы в контакте просто

contact_id, информационная

Самое большое преимущество этого формата, если у вас есть 1 контакт, который находится на MULTIP le applications ... Conatact 'Bob' - contact_1 на 8 разных методах, означает, что информация bob записывается только один раз, и только его идентификатор записывается в таблицу приложений.Biggest ограничения 3 контакта в приложение постоянно закодированы

Alternatively..application может быть определен как APPLICATION_ID, Info и CONACT, как APPLICATION_ID, id_sequence, информация

Преимуществом этой установки является infinate числа контакты могут храниться для каждого приложения.

Хотя все, чтобы удовлетворить ваши потребности ... если у вас всегда есть 3 контакта, второй вариант здесь неадекватен. Если вы не планируете иметь более 1000 записей, наличие всей информации, хранящейся в одной таблице, не является наихудшей идеей (опция в первую очередь исключает избыточные данные). Ответ на ваш вопрос 1 ... в некоторых случаях это слишком много, но ответ будет зависеть от ваших текущих требований и будущих требований. С точки зрения «лучшей практики» настройка таблицы 2 предпочтительнее.

Просто комментарий для вопроса # 2 - Это будет более простая хранимая процедура ... Я не вижу, чтобы это было слишком сложно с вашей настройкой. Возможно, вы можете создать обновляемое представление (не знаете, какие ограничения или проблемы могут возникнуть там, хотя).

0

Каждый отдельный запрос обойдется вам в одночасовое время между клиентами и базами данных в дополнение к чистой стоимости обработки. Таким образом, вы можете сэкономить время в оба конца, если вам удастся выполнить простые одиночные запросы.

Смежные вопросы