Третья нормальная форма — third normal form

Содержание:

Нормализация данных: методы и формулы

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

Графическая интерпретация линейной и нелинейной нормализации

На практике наиболее распространены следующие методы нормализации признаков :

  • Минимакс – линейное преобразование данных в диапазоне , где минимальное и максимальное масштабируемые значения соответствуют 0 и 1 соответственно;
  • Z-масштабирование данных на основе среднего значения и стандартного отклонения: деление разницы между переменной и средним значением на стандартное отклонение;
  • десятичное масштабирование путем удаления десятичного разделителя значения переменной.

Формулы нормализации данных по методам минимакс и Z-масштабирование

На практике минимакс и Z-масштабирование имеют похожие области применимости и часто взаимозаменяемы. Однако, при вычислении расстояний между точками или векторами в большинстве случае используется Z-масштабирование. А минимакс полезен для визуализации, например, чтобы перенести признаки, кодирующие цвет пикселя, в диапазон .

Нормализация НСИ Контрагенты

В результате проведения работ по нормализации данных Контрагенты (Клиенты, Сотрудники, Поставщики, Пациенты, Кредиторы, Дебиторы и пр.) наши клиенты получают данные, соответствующие следующим критериям:

1. Все карточки Контрагентов заполнены полно и без ошибок в реквизитах

При выполнении работ по нормализации данных наши специалисты проверяют все карточки контрагентов, вносят исправления при необходимости и заполняют недостающие данные. При этом они используют как экспертные знания и специализированные методики, так и различные автоматизированные сервисы по проверке и нормализации данных.

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


Рис. 5. Карточка контрагента до и после проведения нормализации.

2. Проведена дедубликация в карточках контрагентов

При выполнении нормализации всей НСИ Контрагенты путем применения специализированных алгоритмов находятся все дубли. Это избавляет домен данных от проблем с ведением всей деятельности по контрагентам в несколько параллельных веток с невозможностью получить точный срез взаимодействия с контрагентами, по которым присутствуют дубли в записях.

В результатах проекта клиенту предоставляются все позиции НСИ, которые являются дублями.

Эффекты от нормализации домена данных Контрагенты

Наши клиенты отмечают следующие позитивные эффекты:

  • возможность ведения централизованной истории взаимодействия по каждому контрагенту без потерь информации;
  •  безошибочное построение любых отчетов, использующих информацию о контрагентах;
  • избежание негативных ситуаций и попадания в «черные списки», например, при работе (e-mail рассылка, обзвон) с существующей клиентской базой, в которой один и тот же клиент, ввиду ошибок, присутствует n-ое количество раз.

Взаимодействие с клиентами при выполнении проектов

Мы открыты в выполнении проектов перед нашими клиентами и стараемся придерживатьcя передовых подходов в том числе и при взаимодействии с клиентами при выполнении проектов.

Нашим клиентам по проектам Нормализации мы предоставляем доступ к личному кабинету через WEB-интерфейс. В личном кабинете сотрудники клиента в режиме реального времени видят текущее состояние выполнения работ. Также этот инструмент используется для выполнения согласования клиентом результатов работ по нормализации.

Если же в силу каких-то причин использование WEB-интерфейсов нежелательно, то при выполнении проектов взаимодействие может вестись с применением табличных файлов Excel и электронной почты.

В отдельных случаях возможно выполнение проектов строго на территории исполнителя. Это актуально при выполнении работ с Оборонными и другими предприятиями специальных режимов.

MinMaxScaler: приведение к диапазону [0,1]

MinMaxScaler в PySpark применяется для шкалирования в диапазоне . Рассчитывается как

X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min
# при min=0, max=1 => X_std = X_scaled

где min и max задаются как минимальное и максимальное допустимое значение, по умолчанию min=0, max=1. Вот так выглядит Python-код для такого вида нормализации:

from pyspark.ml.feature import MinMaxScaler


scaler = MinMaxScaler(inputCol="features", outputCol="scaledFeatures")
scalerModel = scaler.fit(dataFrame)
scaledData = scalerModel.transform(dataFrame)
print("Features scaled to range: " % (scaler.getMin(), scaler.getMax()))
scaledData.select("features", "scaledFeatures").show(truncate=False)

Результат нормализации данных в PySpark:

Features scaled to range: 
+--------------+-----------------------------------------------------------+
|features      |scaledFeatures                                             |
+--------------+-----------------------------------------------------------+
||                                              |
| ||
||                                              |
+--------------+-----------------------------------------------------------+

3НФ — третья нормальная форма

Что такое транзитивная зависимость легко понять на примере уже упоминавшейся выше таблицы продаж — типичного примера ассоциативной таблицы.

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

  • «Идентификатор продажи» => «Номер документа»
  • «Идентификатор продажи» => «Код валюты»
  • «Номер документа» => «Код валюты»

Эти зависимости транзитивны: каждая продажа однозначно определяет свой документ-основание и расчётную валюту, однако, валюта определяется ещё и документом.

Результатом нарушения 3НФ является избыточность хранения и необходимость обновления данных в связанной таблице. Так, если вы оставите колонку «Код валюты» в таблице продаж, то при изменении валюты документа придётся также обновлять все связанные с ним строки продаж.

Сначала поймите разницу между дисперсией, стандартным отклонением и среднеквадратичной ошибкой.

Дисперсия (дисперсия)

Измерьте степень дисперсии (отклонения) случайной величины или набора данных

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

E

(

x

)

E(x)
E(x), Тогда его дисперсия выражается как данные и

E

(

x

)

E(x)
E(x)Сумма квадратов разностей

x

E

(

x

)

2

\sum^2
∑x−E(x)2, А затем найти его ожидание (среднее), чтобы получить

D

(

x

)

=

x

E

(

x

)

2

D(x)=\sum^2
D(x)=∑x−E(x)2

Зачем использовать стандартное отклонение

Согласно вышеизложенному, мы знаем, что дисперсия используется для измерения степени дисперсии (отклонения) случайной величины или набора данных. Формула для стандартного отклонения (также называемая среднеквадратической ошибкой):

σ

=

D

(

x

)

\sigma = \sqrt {D(x)}
σ=D(x)​, Дисперсия и стандартное отклонение имеют общее свойство: чем больше значение, тем более пологая кривая распределения, то есть более разбросанная. Поскольку данные являются случайными, предполагая, что такое же распределение основано на центральной предельной теореме, данные подчиняются распределению Гаусса (нормальному) (типичным примером является ошибка). Давайте посмотрим на область распределения. При использовании стандартного отклонения мы можем четко увидеть вероятность того, что данные принадлежат определенному значению. (Когда мы обрабатываем функции, мы можем отфильтровать выбросы на основе этого)

Рекомендации по использованию в средах отчетности

Хотя 3NF идеален для машинной обработки, сегментированный характер модели данных может быть трудным для восприятия человеком-пользователем. Аналитика с помощью запросов, отчетов и информационных панелей часто упрощалась с помощью модели данных другого типа, которая обеспечивала предварительно рассчитанный анализ, такой как линии тренда, расчеты за период до даты (за месяц, за квартал, за год до даты). на сегодняшний день), кумулятивные вычисления, базовая статистика (среднее, стандартное отклонение, скользящие средние) и сравнения за предыдущие периоды (год назад, месяц назад, неделя назад), например, размерное моделирование и не только размерное моделирование, сглаживание звезд с помощью Hadoop и анализ данных .

Normalizer: применение нормализации к строкам

Normalizer в PySpark необходим для нормализации не атрибутов (столбцов), а записей (строк) путем деления на p-норму . Общая формула выглядит так:

p_norm = sum(X**p) ** (1/p)
X = X / p_norm

Единственным параметром в этом виде нормализации является , причём

  • если p=1, то p-норма равна сумме значений каждой строки;

  • если p=∞, то p-норма равна максимальному значению в каждой строке.

Следующий код на Python демонстрирует результат при p=1:

from pyspark.ml.feature import Normalizer
from pyspark.ml.linalg import Vectors
dataFrame = spark.createDataFrame(),),
    (1, Vectors.dense(),),
    (2, Vectors.dense(),)
], )
normalizer = Normalizer(inputCol="features", outputCol="normFeatures", p=1.0)
l1NormData = normalizer.transform(dataFrame)
print("Normalized using L^1 norm")
l1NormData.show()
#
Normalized using L^1 norm
+---+--------------+------------------+
| id|      features|      normFeatures|
+---+--------------+------------------+
|  0||    |
|  1| |   |
|  2|||
+---+--------------+------------------+

В случае же p=∞  нормализация в PySpark приводит к другим результатам:

lInfNormData = normalizer.transform(dataFrame, {normalizer.p: float("inf")})
print("Normalized using L^inf norm")
lInfNormData.show()
#
Normalized using L^inf norm
+---+--------------+--------------+
| id|      features|  normFeatures|
+---+--------------+--------------+
|  0|||
|  1| | |
|  2|| |
+---+--------------+--------------+

Normalizer можно применять после атрибутивного шкалирования, о которых пойдёт речь дальше.

Демормализация в базе данных: «звезда» и «снежинка»

Как можно понять из вышеприведённых примеров, основными целями нормализации являются:

  • устранение избыточности при хранении данных, приводящей к увеличению размера БД;
  • исключение необходимости модификации данных в связных таблицах для минимизации времени и операций, проводящихся в одной транзакции. Или, как выражаются специалисты, уменьшить толщину транзакции, потому что толстые транзакции мешают при многопользовательской работе взаимными блокировками и увеличением времени отклика системы. Речь об этом пойдёт в отдельной главе.

Но список заявленных целей касается приложений транзакционных.

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

Алгоритм Бернштейна построения схемы БД в НФЭК по множеству ФЗ

Филип Бернштейн предложил алгоритм построения схемы в 3НФ по ФЗ в 1976 г. Позже, Заниоло показал, что схема, построенная по этому алгоритму так же находится в НФЭК.

Данный алгоритм строит, по сути, декомпозицию отношения в 1НФ без потерь и сохраняет зависимости.

Алгоритм может быть описан следующим образом:

Пусть дано множество \(F\) нетривиальных ФЗ. Тогда:

  1. Удалить избыточные атрибуты в детерминантах (левых частях) каждой ФЗ. Получить множество ФЗ \(G\).
  2. Построить неизбыточное покрытие \(H\) для \(G\) (минимизировать \(G\))
  3. Разбить \(H\) на группы таким образом, чтобы левые части ФЗ в каждой группе имели одинаковые левые части.
  4. Объединить эквивалентные ключи. Для каждых двух групп \(H_i\) и \(H_j\), имеющих левыми частями соответственно \(X_i\) и \(X_j\), объединить их, если в \(H^+\) существуют ФЗ \(X_i \to X_j\) и \(X_j \to X_i\).
  5. Составить отношения. Для каждой группы, составить отношение, содержащее атрибуты этой группы. Ключом каждого отношения будут атрибуты детерминанта группы.

Избыточным атрибутом в детерминанте ФЗ \(g \in G\), \(g = X_1, \ldots, X_p \to Y\), является атрибут \(X_i\), если \(G^+\) содержит ФЗ \(X_1, \ldots,X_{i-1}, X_{i+1}, \ldots, X_p \to Y\).

Иначе, для ФЗ \((A \to B) \in G\), атрибут \(a\in A\) является избыточным, если \(a\in (A-\{a\})^+_ G\).

Виды связей между отношениями

Очевидно, что новые отношения, полученные в результате декомпозиции, каким-то образом связаны между собой. Эта связь обеспечивается внешними ключами.

Внешний ключ
Набор атрибутов \(A\) отношения \(R\) называется внешним ключом, если тот же набор атрибутов \(A\), либо некое переименование \(\rho_B A\), является суперключом некого другого отношения \(S\), причем множество значений \(A\) по всем записям \(R\) в любой момент времени является подмножеством значений \(\rho_B A\) по всем записям \(S\).

Выделяется четыре типа связей:

Один к одному (1:1)

Каждой записи отношения \(R\) соответствует одна и только одна запись отношения \(S\), и наоборот.

Нередко оказывается, что отношения \(R\) и \(S\) можно объединить без каких-либо потерь. В таких случаях, единственной причиной сохранять два отношения может быть связь этих отношений с различными сущностями.

Один ко многим (1:M)
Каждой записи отношения \(R\) соответствует \(M \geq 0\) записей отношения \(S\), но каждой записи отношения \(S\) соответствует только одна запись отношения \(R\).
Многие к одному (M:1)
Каждой записи отношения \(R\) соответствует только одна запись отношения \(S\), но каждой записи отношения \(S\) соответствует \(M \geq 0\) записей отношения \(R\)
Многие ко многим (M:N)
Каждой записи отношения \(R\) соответствует \(M \geq 0\) записей отношения \(S\), и каждой записи отношения \(S\) соответствует \(N \geq 0\) записей отношения \(R\)

Связи так же делятся на идентифицирующие и не идентифицирующие.

Идентифицирующая связь

это такая связь, которая требует существования значения первичного ключа связанного отношения. Иными словами, запись в связанном отношении необходима для идентификации записи в данном.

Например, даны отношения Directory = (Id, Name) и File = (Id, Name, DirectoryId), связанные 1:М через внешний ключ File.DirectoryId ⇆ Directory.Id. В данной модели, файл не может существовать без директории, и эта связь является идентифицирующей, поскольку требует существования значения Directory.Id, равного File.DirectoryId.

Не идентифицирующая связь

связь, не являющаяся идентифицирующей.

Например, даны два отношения Account = (Id, Type) и AccountType = (Type, Description), связанные M:1 через внешний ключ Account.Type ⇆ AccountType.Type. В данной модели Type может быть не задан. Такое отношение не будет идентифицирующим, поскольку записи в Account и AccountType могут существовать независимо друг от друга.

Проектирование баз данных

Проектирование баз данных – это процесс концептуализации и реализации базы данных, описывающих некую предметную область, для встраивания в конкретную СУБД.

Обычно выделяют следующие этапы проектирования БД:

  1. Концептуальное (инфологическое) проектирование.
  2. Логическое (даталогическое) проектирование
  3. Физическое проектирование

Рассмотрим эти этапы более подробно.

Нормализация и стандартизация — методы шкалирования данных

Нормализация (normalization) и стандартизация (standardization) являются методами изменения диапазонов значений – шкалирования. Шкалирование особенно полезно в машинном обучении (Machine Learning), поскольку разные атрибуты могут измеряться в разных диапазонах, или значения одного атрибута варьируются слишком сильно. Например, один атрибут имеет диапазон от 0 до 1, а второй — от 1 до 1000. Для задачи регрессии второй атрибут оказывал бы большое влияние на обучение, хотя не факт, что он является более важным, чем первый. Нормализация и стандартизация отличаются своими подходами:

  • Нормализация подразумевает изменение диапазонов в данных без изменения формы распределения,

  • Стандартизация изменяет форму распределения данных (приводится к нормальному распределению).

Обычно достаточно нормализовать данные. Например, в глубоком обучении (Deep Learning) требуется перевести цвета изображений RGB из диапазона 0-255 к диапазону 0-1. А вот стандартизацию стоит применять при использование алгоритмов, которые основываются на измерении расстояний, например, k ближайших соседей или метод опорных векторов (SVM).

Классический пример приведения таблиц базы данных к четвертой нормальной форме

Чтобы стало еще понятней, давайте закрепим знания и рассмотрим классический пример, который обычно используется в литературе для пояснения четвертой нормальной формы.

Таблица связей студентов, курсов и хобби.

Студент Курс Хобби
Иванов И.И. SQL Футбол
Иванов И.И. Java Хоккей
Сергеев С.С. SQL Волейбол
Сергеев С.С. SQL Теннис
John Smith Python Футбол
John Smith Java Теннис

Данная таблица хранит информацию о студентах, в частности здесь хранятся курсы, которые посещает студент, и увлечения этого студента, т.е. хобби.

Отсюда следует, что каждый студент может посещать несколько курсов и иметь несколько увлечений.

Первичный ключ здесь также составной и состоит он из всех трех столбцов.

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

Таким образом, мы можем наблюдать в этой таблице нетривиальную многозначную зависимость

Студент ->-> Курс

Студент ->-> Хобби

Поэтому эта таблица не находится в четвертой нормальной форме.

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

Допустим, нам необходимо получить информацию о хобби студентов, которые посещают курс по SQL. Очевидным действием станет выборка с условием Курс = SQL, в результате мы получим 3 хобби: футбол, волейбол и теннис.

Результат выборки. Хобби студентов, которые посещают курс по SQL.

Студент Курс Хобби
Иванов И.И. SQL Футбол
Сергеев С.С. SQL Волейбол
Сергеев С.С. SQL Теннис

Однако, если мы заглянем в исходную таблицу, то мы четко увидим, что «Иванов И.И.» посещает курс по SQL и имеет хобби «Хоккей», но в нашей выборке этого хобби нет.

Чтобы нормализовать эту таблицу, мы должны точно так же, как и в предыдущем примере, разбить ее на две.

 Связь студентов и курсов.

Студент Курс
Иванов И.И. SQL
Иванов И.И. Java
Сергеев С.С. SQL
John Smith Python
John Smith Java

Связь студентов и хобби.

Студент Хобби
Иванов И.И. Футбол
Иванов И.И. Хоккей
Сергеев С.С. Волейбол
Сергеев С.С. Теннис
John Smith Футбол
John Smith Теннис

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

И если говорить о реальных данных, то нормализация до четвертой нормальной формы, как и до всех последующих, в современном мире практически не встречается. Если четвертую нормальную форму еще как-то можно представить и даже встретить данные, нормализованные до этой формы, то встретить данные, нормализованные до 5 или 6 нормальной формы, практически невозможно.

Вы можете спросить, а почему не нормализуют данные до 5 или 6 нормальной формы? Ведь каждая нормальная форма устраняет определенные аномалии, и если сделать полностью нормализованную базу данных, то по сути она будет идеальная, не содержащая ни одной аномалии, это же хорошо.

Да, совершенно верно, база данных не будет содержать аномалий, но давайте вспомним, какие преимущества нам дает нормализация.

Обычно во всех источниках приводится два основных глобальных преимущества:

  • Устранение аномалий
  • Повышение производительности

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

Да, нормализация повышает производительность, но только где-то до 3 нормальной формы. Начиная с 4 нормальной формы, производительность увеличиваться не будет, более того, с каждой новой формой производительность будет значительно снижаться, не говоря уже о том, что с нормализованной базой данных до 5 или 6 нормальной формы будет крайне сложно и неудобно работать и сопровождать ее, ведь с каждой новой формой мы значительно увеличиваем количество таблиц в базе данных.

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

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

Полностью нормализованная база данных – это плохая база данных.

После того как мы привели таблицы базы данных к четвертой нормальной форме, мы можем переходить к приведению таблиц до пятой нормальной формы (5NF). Описание, требования и пример приведения таблиц до пятой нормальной формы мы рассмотрим в следующем материале.

На сегодня это все, надеюсь, материал был Вам полезен, пока!

Нравится43Не нравится

Нормализация базы данных

Нормализация базы данных – это рекомендации по проектированию.

Преимущества нормализованной базы данных:

  • Возможность существенно упростить выборки. Получение данных из базы относительно простыми запросами.
  • Целостность данных. Избежание потерь или искажения информации в базе данных.
  • Отсутствие избыточности. Данные в таблице не дублируются, что существенно снижает её размер.
  • Благоприятные предпосылки к росту базы.

Как привести базу данных к нормальной форме?

Для приведения базы к нормальной форме необходимо выполнить следующие действия:

  1. Постараться объединить данные в группы.
  2. Найти логические связи между этими группами данных. Для установки связей связываемые поля должны быть одного типа и таблица формата InnoDB.

Существует 3 нормальные формы базы данных:

  1. Первая нормальная форма
     

    Таблица представляет сущность которая в ней размещена (например клиенты, заказы и т.д.) Причём в каждой таблице имеется уникальное поле (первичный ключ) например id и каждая таблица состоит из наименьшего количества полей.
     
    Пример №1:

    id name languages
    1 Иван Java, C++, PHP
    2 Пётр PHP, JavaScript
    3 Михаил C#, JavaScript

    В примере №1. Представлена не удачная структура таблицы, где в поле languages указано перечисление.
     
    Пример №2:

    id name languages1 languages2 languages3
    1 Иван Java C++ PHP
    2 Пётр PHP JavaScript NULL
    3 Михаил C# JavaScript NULL

     
    В примере №2 тоже не верная структура таблицы для поля languages.
     
    Правильная структура таблиц для решения данной задачи:
     
     
    Пример №3:
     

    Таблица пользователей

    id name languages
    1 Иван Java, C++, PHP
    2 Пётр PHP, JavaScript
    3 Михаил C#, JavaScript

    Таблица языков программирования

    id language
    1 Java
    2 PHP
    3 C#
    4 JavaScript
    5 Java

    Таблица связей между пользователями и языками программирования

    id language_id user_id
    1 2 1
    2 1 1
    3 5 1
    4 1 2
  2. Вторая нормальная форма
    Для второй нормальной формы требуется первая нормальная форма.

    Пример №4:

    id make model
    1 bmw X5
    2 bmw X6
    3 audi A4
    4 audi Q5
    5 toyota corolla

    В примере №4 мы видим дублирование некоторых марок автомобилей (Данные избыточны). Требуется сделать разделение на несколько таблиц как в примере №3. На первый взгляд создание новых таблиц кажется более затратным чем реализация в примере №4, но это только до тех пор когда таблица состоит всего из нескольких строк.
     
    Правильная структура таблиц для решения данной задачи:

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

    Пример №5:

    Таблица цен и цен с НДС

    id price price_nds
    1 1100 1243
    2 950 1074

    Так как цену с НДС можно получить из поля price, то данную задачу нужно переложить на язык программирования.

Заключение

Продолжать заниматься нормализацией можно и дальше: существуют 4NF, 5NF и DKNF (Domain Key Normal Form). Использование четырех уровней нормализации, рассмотренных в этой статье, является вполне достаточным в большинстве случаев проектирования баз данных. Таблицы могут быть нормализованы и до более высоких типов, но на практике это бывает не всегда возможно. Недостатком при стремлении к более высоким уровням нормализации является то, что таблицы могут быть разложены на более меньшие, чтобы отразить все возможные зависимости.

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

Источник статьи — Источник статьи — http://www.developer.com/db/understanding-database-normalization.html

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector