как структурировать таблицу mysql, чтобы как можно меньше нагружать базу данных (с использованием hibernate)

#mysql #database #hibernate #database-design

#mysql #База данных #режим гибернации #база данных-дизайн

Вопрос:

У меня возник один вопрос о структуре базы данных при использовании hibernate.

Я должен сохранять информацию (одно число) за каждый день в базе данных. Очень часто мне нужно выбирать информацию за целый месяц.

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

Теперь я подумал о том, чтобы записать всю информацию (31 число) в таблицу МЕСЯЦЕВ со столбцом «месяц» и другим столбцом «информация», куда я вставил все числа, разделенные символом «;». Тогда мне нужно было бы сделать только один выбор. Но мне пришлось бы разделить datarecord, чтобы получить числа (разделять при каждом «;»).

Так что, возможно, другим решением была бы таблица МЕСЯЦЕВ с 32 столбцами (месяц и с 1 по 31). столбцы от 1 до 31 были бы tinyints, и я бы сохранил в них числа. Мне пришлось бы сделать один выбор, чтобы получить данные за каждый месяц, и мне не пришлось бы разделять datarecord, но я мог бы запросить данные по столбцу (я использую hibernate)

Есть ли у этого последнего решения какие-либо недостатки, о которых я не подумал? 🙂 Вы бы порекомендовали другое решение?

[РЕДАКТИРОВАТЬ] Спасибо за вашу помощь. Такой была структура данных раньше:

 create table CLIENTS_DATA (
client_id int UNSIGNED NOT NULL, 
datum date NOT NULL, 
information tinyint UNSIGNED NOT NULL default 0, 
** additional informations **
primary key(client_id, datum),
foreign key(client_id) references clients(id) ON DELETE CASCADE ON UPDATE CASCADE) 
ENGINE=InnoDB;
  

и вот теперь я хранил информацию в течение целого месяца в:

 create table CLIENTS_MONTHLY_INFORMATIONS (
client_id int UNSIGNED NOT NULL,
datum date NOT NULL,
i1 tinyint NOT NULL default 0,
i2 tinyint NOT NULL default 0,
i3 tinyint NOT NULL default 0,
i4 tinyint NOT NULL default 0,
i5 tinyint NOT NULL default 0,
i6 tinyint NOT NULL default 0,
i7 tinyint NOT NULL default 0,
i8 tinyint NOT NULL default 0,
i9 tinyint NOT NULL default 0,
i10 tinyint NOT NULL default 0,
i11 tinyint NOT NULL default 0,
i12 tinyint NOT NULL default 0,
i13 tinyint NOT NULL default 0,
i14 tinyint NOT NULL default 0,
i15 tinyint NOT NULL default 0,
i16 tinyint NOT NULL default 0,
i17 tinyint NOT NULL default 0,
i18 tinyint NOT NULL default 0,
i19 tinyint NOT NULL default 0,
i20 tinyint NOT NULL default 0,
i21 tinyint NOT NULL default 0,
i22 tinyint NOT NULL default 0,
i23 tinyint NOT NULL default 0,
i24 tinyint NOT NULL default 0,
i25 tinyint NOT NULL default 0,
i26 tinyint NOT NULL default 0,
i27 tinyint NOT NULL default 0,
i28 tinyint NOT NULL default 0,
i29 tinyint NOT NULL default 0,
i30 tinyint NOT NULL default 0,
i31 tinyint NOT NULL default 0,
average float UNSIGNED,
primary key(client_id, datum),
foreign key(client_id) references clients(id) ON DELETE CASCADE ON UPDATE CASCADE) 
ENGINE=InnoDB;
  

запрос для второй таблицы будет:

 public ClientsMonthlyInformations getClientsMonthlyInformationsByIdAndDate(int uid, Date datum) {

ClientsMonthlyInformations cmi = (ClientsMonthlyInformations) this.sessionFactory.getCurrentSession().createQuery("from ClientsMonthlyInformations clientsmonthlyinformations where clientsmonthlyinformations.clients.id=:clientsid and clientsmonthlyinformations.datum=:date").setParameter("clientsid", uid).setParameter("date", datum).uniqueResult();

return cmi;
}
  

для получения данных из первой таблицы я использую ту же запись, но, конечно, ClientsData вместо Clientsmonth-lyinformation. Вы правы, я мог бы создать запрос для получения 31 Datarecords, что означает 31 объект Hibernate. Я не знаю, почему я думал, что выполнение одного выбора в 31 строке для получения 31 объекта было бы плохо.

Комментарии:

1. Почему у вас просто нет столбца с датой? Вы все еще можете выполнять выбор на основе значения столбца date.

2. Было бы полезно, если бы вы опубликовали свою структуру таблицы и SELECT запросы. Это как-то нехорошо звучит, когда я читаю, что вы запрашиваете до 31 раза в месяц, что-то указывает на плохой дизайн, поскольку вы должны быть в состоянии сделать это за 1 запрос.

Ответ №1:

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

Часто определять? Сколько дней у вас в настоящее время есть? Если это не происходит более 20 раз в секунду, не должно быть какого-либо измеримого воздействия на базу данных.

Теперь я подумал о том, чтобы записать всю информацию (31 число) в таблицу МЕСЯЦЕВ

Это действительно глупая идея, и она не решит проблему.

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

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

  SELECT DATE_FORMAT(a.date, '%Y-%m'), GROUP_CONCAT(metric)
 FROM (
     SELECT a.date, a.metric
     FROM your_table a
     WHERE a.date>20110101000000
     ORDER BY a.date
 )
 GROUP BY DATE_FORMAT(a.date, '%Y-%m');
  

(предполагая, что вы хотите вывод в денормализованной структуре — и абсолютно уверены, что нет пропущенных / повторяющихся дней)

Комментарии:

1. как я писал выше, возможно, я был неправ. Я разместил свою структуру таблицы выше. Возможно, я мог бы запросить 31 нужную мне информацию одним select, это правда. Тогда я бы получил 31 объект Hibernate. Я не знаю, но я почему-то подумал, что это не будет хорошей идеей. — ну, и это не более 20 раз в секунду — не сейчас! но почему бы не сделать базу данных максимально совершенной, в будущем может быть намного больше выборок.