Мне нужно сохранить ряд значений конфигурации в базе данных. Несколько способов, которые я думал о их хранении, - это таблица с двумя колонами (имя, значение) и строка для каждой пары или таблица со столбцом для каждого параметра конфигурации и 1 строка? Сперва мне нужно добавить еще одну строку, чтобы добавить значение конфигурации, а второе мне нужно добавить столбец в таблицу. Есть ли какие-либо проблемы с тем, что я должен принять к рассмотрению? Является ли более эффективным, чем другой?
Лучший дизайн таблицы для настройки приложения или параметров приложения?
Ответ 1
Для данных конфигурации я бы использовал структуру key/value со строкой для каждой записи конфигурации. Вероятно, вы прочитаете эти данные один раз и кешируете его, поэтому производительность не является проблемой. Как вы отмечаете, добавление столбцов каждый раз, когда изменяется набор ключей конфигурации, требует гораздо больше обслуживания.
SQL превосходит при моделировании и манипулировании произвольно большими наборами аналогичных (если не одинаковых) структурированных данных. Набор информации о конфигурации действительно не таков: у вас есть одна строка данных или у вас есть несколько строк абсолютно несвязанных данных. Это говорит о том, что вы просто используете это как хранилище данных. Я говорю пропустить модель данных SQL и простую.
Ответ 2
Еще одно соображение: с столбцом для каждого параметра конфигурации вы можете легко иметь версии. Каждая строка представляет собой версию.
Ответ 3
Одним из недостатков использования отдельной строки для каждого параметра (приложения) конфигурации (или параметра приложения) является то, что вы не можете сохранить значения параметров в столбце с соответствующим типом данных. Могут ли пользователи вводить данные с недопустимым типом? Это относится к вашему приложению?
Одно из преимуществ использования отдельных столбцов заключается в том, что любой код в вашей базе данных (например, хранимые процедуры, функции и т.д.) может использовать значение соответствующего типа данных, не требуя сначала проверки недопустимых значений, а затем преобразования в соответствующий тип данных.
Если вы вручную развертываете изменения в своей прикладной БД, тогда да, если вы используете дизайн EAV, очень немного проще развернуть новые параметры конфигурации, но действительно, что сэкономить на:
INSERT Options ( ConfigurationSetting, Value )
VALUES ( 'NewConfigurationSetting', NewConfigurationSettingValue )
против
ALTER TABLE Options ADD NewConfigurationSetting some_datatype
UPDATE Options
SET NewConfigurationSetting = NewConfigurationSettingValue
Ответ 4
Первым вопросом, который вы должны рассмотреть, является следующее: перестать думать об эффективности извлечения информации. в первую очередь, выяснить, как эффективно и правильно моделировать данные, а затем (и только потом) выяснить, как это сделать эффективно.
Таким образом, это зависит от характера хранимых конфигурационных данных. Если отдельные (имя, значение) пары в основном не связаны друг с другом, сохраните их как одну строку. Если они связаны, вы можете рассмотреть схему с несколькими столбцами.
Что я имею в виду? Рассмотрим конфигурацию кеша. Каждый кеш имеет несколько атрибутов:
- политика выселения;
- время истечения срока действия;
- максимальный размер.
Предположим, что у каждого кеша есть имя. Вы можете сохранить эти данные в виде трех строк:
-
<name>_EVICTION
-
<name>_EXPIRY
-
<name>_MAX_SIZE
но эти данные связаны между собой, и вам часто может потребоваться сразу их загрузить. В этом случае имеет смысл иметь таблицу cache_config с пятью столбцами: id, name, eviction, expiry, max_size.
Что я имею в виду по связанным данным.
Ответ 5
Я думаю, что дизайн 2-coumn (имя, значение) намного лучше. Как вы сказали, если вам нужно добавить новое свойство, все, что вам нужно сделать, это "insert
" новая строка. Хотя в другом проекте (однострочном) вам нужно изменить схему таблицы, чтобы добавить столбец для нового свойства.
Это, однако, зависит от того, изменится ли ваш список свойств в будущем.
Ответ 6
Эффективное сохранение конфигурации с помощью XML. Некоторая поддержка базы данных Функция чистого XML, в которой вы можете сохранить значение как тип данных xml, и вы можете запустить XQUERY в этом конкретном столбце.
Создайте таблицу с двумя именами столбцов и конфигурацией. имя с строковым типом данных и конфигурацией с типом данных xml, поэтому не нужно беспокоиться о вставке и удалении новых параметров конфигурации, вы просто новый тег в xml. И если база данных не поддерживает XML, просто сохраните ее как строку, но в формате XML, чтобы вы могли анализировать эту конфигурацию вручную или с помощью некоторого API эффективно.
Я думаю, что это было бы лучше, вместо сохранения полной конфигурации в виде строки.
Ответ 7
Здесь я рассказываю о том, когда мы переместили нашу AppSettings в таблицу базы данных. Производительность не является проблемой, потому что она тянет только один раз в начале приложения и хранится в словаре для удобного поиска.
Не уверен в отношении вашего приложения, но важная причина, почему мы это сделали, теперь невозможно использовать значения Production, если вы находитесь в Dev, Test и т.д.
Ответ 8
Я DESPISE помещаю нестроковые значения в строковый столбец (иначе, неверные типы данных). (Как обсуждает @Kenny Evitt)
Итак, я придумал альтернативу , которая идет по вертикали и имеет дело с правильными типами данных.
На самом деле я не использую деньги и мелкие деньги. Но я включил их для полноты. Обратите внимание, что есть несколько других типов данных
см
https://msdn.microsoft.com/en-us/library/ms187752.aspx?f=255&MSPPError=-2147217396
Но нижняя часть охватывает большинство вещей.
честно говоря, я использую только строку (varchar (1024)), int, smallint и бит... 99% времени.
Это не идеально. Ака, у тебя много нулевых кортежей. Но поскольку вы только захватываете эти один раз (и кеш), сопоставление с объектом настроек (в С# в моем мире) не сложно.
CREATE TABLE [dbo].[SystemSetting](
[SystemSettingId] [int] IDENTITY NOT NULL,
[SettingKeyName] [nvarchar](64) NOT NULL,
[SettingDataType] [nvarchar](64) NOT NULL, /* store the datatype as string here */
[SettingValueBigInt] bigint NULL,
[SettingValueNumeric] numeric NULL,
[SettingValueSmallInt] smallint NULL,
[SettingValueDecimal] decimal NULL,
[SettingValueSmallMoney] smallmoney NULL,
[SettingValueInt] int NULL,
[SettingValueTinyInt] tinyint NULL,
[SettingValueMoney] money NULL,
[SettingValueFloat] float NULL,
[SettingValueReal] real NULL,
[SettingValueDate] date NULL,
[SettingValueDateTimeOffSet] datetimeoffset NULL,
[SettingValueDateTime2] datetime2 NULL,
[SettingValueSmallDateTime] smalldatetime NULL,
[SettingValueDateTime] datetime NULL,
[SettingValueTime] time NULL,
[SettingValueVarChar] varchar(1024) NULL,
[SettingValueChar] char NULL,
[InsertDate] [datetime] NOT NULL DEFAULT (GETDATE()),
[InsertedBy] [nvarchar](50) NOT NULL DEFAULT (SUSER_SNAME()),
[LastUpdated] [datetime] NOT NULL DEFAULT (GETDATE()),
[LastUpdatedBy] [nvarchar](50) NOT NULL DEFAULT (SUSER_SNAME()),
)
Теперь, если это слишком много, и вы решили использовать "строки" для всех значений, то вот несколько DDL.
DROP TABLE [dbo].[SystemSetting]
DROP TABLE [dbo].[SystemSettingCategory]
CREATE TABLE [dbo].[SystemSettingCategory] (
[SystemSettingCategoryId] [int] NOT NULL,
[SystemSettingCategoryName] [nvarchar](64) NOT NULL,
[InsertDate] [datetime] NOT NULL DEFAULT (GETDATE()),
[InsertedBy] [nvarchar](50) NOT NULL DEFAULT (SUSER_SNAME()),
[LastUpdated] [datetime] NOT NULL DEFAULT (GETDATE()),
[LastUpdatedBy] [nvarchar](50) NOT NULL DEFAULT (SUSER_SNAME()),
CONSTRAINT [PK_SystemSettingCategory] PRIMARY KEY CLUSTERED ([SystemSettingCategoryId] ASC),
CONSTRAINT UQ_SystemSettingCategoryName UNIQUE NONCLUSTERED ([SystemSettingCategoryName])
)
CREATE TABLE [dbo].[SystemSetting] (
[SystemSettingId] [int] NOT NULL,
[SystemSettingCategoryId] INT NOT NULL, /* FK to [SystemSettingCategory], not shown here */
[SettingKeyName] [nvarchar](64) NOT NULL,
[SettingValue] nvarchar(1024) NULL,
[InsertDate] [datetime] NOT NULL DEFAULT (GETDATE()),
[InsertedBy] [nvarchar](50) NOT NULL DEFAULT (SUSER_SNAME()),
[LastUpdated] [datetime] NOT NULL DEFAULT (GETDATE()),
[LastUpdatedBy] [nvarchar](50) NOT NULL DEFAULT (SUSER_SNAME()),
CONSTRAINT [PK_SystemSetting] PRIMARY KEY CLUSTERED ([SystemSettingId] ASC),
CONSTRAINT FK_SystemSettingCategory_SystemSettingCategoryId foreign key ([SystemSettingCategoryId]) references [SystemSettingCategory] ([SystemSettingCategoryId]),
CONSTRAINT UQ_SystemSettingCategoryId_SettingKeyName UNIQUE NONCLUSTERED ( [SystemSettingCategoryId] , [SettingKeyName] )
)
INSERT INTO [dbo].[SystemSettingCategory] ( [SystemSettingCategoryId] , [SystemSettingCategoryName] )
select 101 , 'EmployeeSettings' UNION ALL select 201, 'StopLightSettings'
INSERT INTO [dbo].[SystemSetting] ( [SystemSettingId] , [SystemSettingCategoryId] , [SettingKeyName] , [SettingValue] )
select 1001 , 101 , 'MininumAgeRequirementMonths' , convert(varchar(16) , (12 * 18))
UNION ALL select 1002 , 101 , 'MininumExperienceMonths' , convert(varchar(8) , 24)
UNION ALL select 2001 , 201 , 'RedLightPosition' , 'top'
UNION ALL select 2002 , 201 , 'YellowLightPosition' , 'middle'
UNION ALL select 2003 , 201 , 'GreenLightPosition' , 'bottom'
/* should fail */
/* start
INSERT INTO [dbo].[SystemSettingCategory] ( [SystemSettingCategoryId] , [SystemSettingCategoryName] )
select 3333 , 'EmployeeSettings'
INSERT INTO [dbo].[SystemSettingCategory] ( [SystemSettingCategoryId] , [SystemSettingCategoryName] )
select 101 , 'xxxxxxxxxxxxxx'
INSERT INTO [dbo].[SystemSetting] ( [SystemSettingId] , [SystemSettingCategoryId] , [SettingKeyName] , [SettingValue] )
select 5555 , 101 , 'MininumAgeRequirementMonths' , 555
INSERT INTO [dbo].[SystemSetting] ( [SystemSettingId] , [SystemSettingCategoryId] , [SettingKeyName] , [SettingValue] )
select 1001 , 101 , 'yyyyyyyyyyyyyy' , 777
INSERT INTO [dbo].[SystemSetting] ( [SystemSettingId] , [SystemSettingCategoryId] , [SettingKeyName] , [SettingValue] )
select 5555 , 555 , 'Bad FK' , 555
end */
Select * from [dbo].[SystemSetting] where [SystemSettingCategoryId] = 101 /* employee related */
Select * from [dbo].[SystemSetting] where [SystemSettingCategoryId] = 201 /* StopLightSettings related */
Теперь, сделав это намного дальше, вы все равно можете создать сильно типизированные объекты dotnet с правильными типами данных, а затем преобразовать ваш datareader/dataset в сильный объект, как показано ниже.
public class EmployeeSettings
{
public Int16 MininumAgeRequirementMonths { get; set; }
public Int16 MininumExperienceMonths{ get; set; }
}
public class StopLightSettings
{
public string RedLightPosition { get; set; }
public string YellowLightPosition { get; set; }
public string GreenLightPosition { get; set; }
}
Вы все еще можете использовать классы С# (или любой другой язык)........ и использовать метод SettingDataType выше. Код "mapping" просто нуждается в небольшой дополнительной работе.
Если не отменено, я использую классы SettingDataType и С#, как показано выше.
Ответ 9
CREATE TABLE Configuration (
Name ...,
Value ...,
);
Лучший способ. Добавление столбца в таблицу обычно отстой, а какая точка таблицы с одной строкой?
Не уверен, что это подходит для SQL, но, увы... вопрос ответил.
Ответ 10
Я использовал оба метода, и я предпочитаю метод с двумя столбцами. Возврат к новому столбцу для каждой конфигурации - это изменение кода для добавления новых параметров.
Я предпочитаю использовать один столбец для каждого метода установки (когда я обращаюсь к значению). Это связано с тем, что настройки конфигурации более явно заданы. Но это предпочтение не учитывает трудности добавления новой конфигурации в таблицу.
Я бы рекомендовал метод с двумя столбцами. Затем настройте функцию доступа /sproc, чтобы получить значения.
Ответ 11
зависит.
Если у вас меньше 15 значений, я бы сделал столбцом для каждого.
Если вы регулярно изменяете количество настроек или часто не используете все настройки, я бы подумал о создании строки для каждой настройки.
Помимо этого, это, вероятно, tossup. Зависит от ваших шаблонов использования. Если вам всегда нужно ухватить все настройки, это, вероятно, быстрее всего будет в одной строке.
Добавление столбцов не слишком сложно, и если вы программируете разумно, вам обычно не нужно обновлять какой-либо другой код.
Ответ 12
"Лучшее" полностью зависит от контекста - как будут использоваться эти данные?
Если все, что вам нужно сделать, это сохранить и получить один набор параметров конфигурации, я бы поставил под вопрос использование реляционной базы данных в первую очередь - он не добавляет очевидной выгоды по сравнению с файлами конфигурации в файловой системе. Вы не можете легко использовать контроль версий для своих конфигурационных файлов, а также управлять различиями в среде (например, "DEV", "TEST" и "ПРОИЗВОДСТВО" ) теперь требуется графический интерфейс для изменения базы данных (о, и как вы подключаетесь к база данных в первую очередь?).
Если вашему приложению необходимо "обосновать" конфигурацию в целом - например, если у вас есть решение для нескольких арендаторов и вам необходимо динамически настроить приложение на основе текущей системы - я бы предложил сохранить файлы конфигурации в виде текстового документа в вашей базе данных, с метаданными, которые позволяют приложению хранить/извлекать документ, Различные базы данных имеют разные решения для хранения текстовых документов. Например, в многоуровневой системе вы можете:
ID client_id valid_from valid_until configuration_file
-------------------------------------------------------
1 1 2016/03/16 NULL <<DOCUMENT>>
Это позволит вам получить файл для клиента 1, который был действителен после 3 марта, и выполнять все, что требуется приложению.
Если вашему приложению необходимо обосновать содержимое конфигурации, а не настройку как самостоятельную сущность, у вас есть другая проблема. Предлагаемое вами решение "имя/значение" также называется Entity/Attribute/Value (EAV), и есть лоты fooobar.com/info/162252/... questions обсуждать преимущества и недостатки. TL; DR: трудно конвертировать даже простые вопросы в SQL при использовании EAV.
Гораздо проще запрашивать данные, если каждый параметр конфигурации является столбцом с соответствующим типом данных. Но это означает, что у вас заканчивается очень "широкая" таблица (большинство приложений имеют десятки или даже сотни значений конфигурации), и каждый раз, когда вы хотите добавить параметр конфигурации, вы в конечном итоге модифицируете схему базы данных, Практически.
Альтернативой, таким образом, является сохранение значений конфигурации в виде структурированного документа - XML и JSON широко поддерживаются. Эти форматы могут запрашиваться механизмом базы данных, но не требуют фиксированной схемы.