#mysql #database #database-design #lazy-loading
#mysql #База данных #database-design #отложенная загрузка
Вопрос:
Простой вопрос: должны ли ДОПОЛНИТЕЛЬНЫЕ пользовательские настройки быть лениво инициализированы в БД или всегда создаваться с новой регистрацией?
Пользователь может устанавливать дополнительные необязательные настройки, поэтому должна ли строка для этого необязательного параметра создаваться для каждого пользователя при регистрации или создаваться только тогда, когда пользователь впервые использует эти настройки?
Ленивая инициализация экономит место, поэтому я склоняюсь к тому, чтобы делать это таким образом, но я не уверен, есть ли какие-либо недостатки.
Ответ №1:
Выполните ленивую инициализацию. Вот почему .. если вместо этого вы использовали значения по умолчанию для настроек, которые пользователь активно не выбирал, а затем позже бизнес-правила изменились, чтобы установить значение по умолчанию на что-то другое, у вас будут пользователи с настройками, которые кажутся настройками по умолчанию, которые они активно не выбирали.
Ответ №2:
Вот один конкретный недостаток, с которым я столкнулся при использовании ленивой инициализации в MySQL. Все это сводится к этой цитате из документов MySQL:
Определяемые пользователем переменные зависят от соединения.
Во-первых: настройка
Подключитесь к своей БД (в моем случае MySQL), затем создайте простую функцию SetBarProperty(), которая ЯВНО устанавливает для свойства @bar значение, переданное функции. Сама функция просто возвращает переданное ей значение.
$ mysql
mysql> DROP FUNCTION IF EXISTS SetBarProperty;
Query OK, 0 rows affected (0.01 sec)
mysql> DELIMITER $$
mysql> CREATE FUNCTION SetBarProperty( myValue INT(30) )
-> RETURNS INT(30)
-> DETERMINISTIC
-> READS SQL DATA
-> BEGIN
-> SET @bar := myValue;
-> RETURN myValue;
-> END $$
Query OK, 0 rows affected (0.01 sec)
mysql> DELIMITER ;
Теперь, если мы запросим свойство @bar, оно будет NULL, как и ожидалось.
mysql> SELECT @bar;
------
| @bar |
------
| NULL |
------
1 row in set (0.00 sec)
Опять же, если мы вызовем SetBarProperty(3); результат будет таким, как и ожидалось.
mysql> SELECT SetBarProperty(3);
-------------------
| SetBarProperty(3) |
-------------------
| 3 |
-------------------
1 row in set (0.00 sec)
Что вы думаете?
Как вы думаете, что произойдет, если мы вызовем следующий запрос?
SELECT SetBarProperty(4), @bar;
Вы угадали! @bar равно 4.
mysql> SELECT SetBarProperty(4), @bar;
------------------- ------
| SetBarProperty(4) | @bar |
------------------- ------
| 4 | 4 |
------------------- ------
1 row in set (0.00 sec)
А теперь сложная часть…
Отключитесь от вашего сервера БД (это очень важно):
Ctrl C
Теперь повторно подключитесь и вызовите тот же запрос, что и раньше:
$ mysql
mysql> SELECT SetBarProperty(4), @bar;
------------------- ------
| SetBarProperty(4) | @bar |
------------------- ------
| 4 | NULL |
------------------- ------
1 row in set (0.00 sec)
Вы видели, что только что произошло?
Значение @bar было нулевым, и это связано с тем, что оно не было инициализировано в вызывающем пространстве функции SetBarProperty() .
Если вы отключитесь от своей БД и явно инициализируете свойство ПЕРЕД вызовом функции (которая сама инициализирует его эксплицитно), ваш запрос работает так, как ожидалось:
Ctrl C
$ mysql
mysql> SET @bar := NULL;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT SetBarProperty(4), @bar;
------------------- ------
| SetBarProperty(4) | @bar |
------------------- ------
| 4 | 4 |
------------------- ------
1 row in set (0.00 sec)
Рекомендация
Если вы немедленно используете свойство в запросе сразу после вызова функции, которая изменяет то же свойство, вы должны инициализировать свойство перед вызовом функции.
Надеюсь, это поможет!
С уважением,
Konrad