如何构建 mysql 表以尽可能减少对数据库的压力(使用 hibernate)

发布于 2024-11-08 06:04:24 字数 2757 浏览 0 评论 0原文

我在使用 hibernate 时有一个关于数据库结构的问题。

我必须在数据库中保存每天的信息(一个数字)。 很多时候我需要选择一整月的信息。

当我得到一张包含(日期、信息)的表时,我必须执行最多 31 次选择才能获取一个月的数据。由于我经常这样做,它会给数据库带来压力。

现在我想将整个信息(31个数字)写入一个月表,其中有一列“月”和另一列“信息”,我在其中放入所有数字,并用“;”分隔。那么我只需要做一项选择。但我必须拆分数据记录才能获取数字(按每个“;”拆分)。

因此,也许另一种解决方案是 MONTH-Table,包含 32 列(月份和 1 到 31)。 1 到 31 列将是tinyints,我将在其中存储数字。 我必须做出一个选择来获取每个月的数据,并且我不必拆分数据记录,但可以请求每列的数据(我使用休眠)

最后一个解决方案是否有任何我没有想到的缺点? :-) 您会推荐另一种解决方案吗?

[编辑] 感谢您的帮助。这是之前的数据结构:

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 而不是 ClientsMonthlyInformation 。你是对的,我可以创建一个查询来获取 31 个数据记录,这意味着 31 个 Hibernate 对象。我不知道为什么我认为对 31 行进行一次选择来获取 31 个对象会很糟糕。

I've got one question about the structure of a database when using hibernate.

I have to save information (one number) for every day in the database.
Very often I need to select the information for a whole month.

When Ive got a table with (date, information), then I have to do up to 31 selects to get the data for one month. As I do this very often, it stresses the database.

Now I thought of writing the whole information (31 numbers) into a MONTH-table, with a column "month" and another column "information", where I put in all the numbers separated by a ";". Then I would only have to do one select. But I would have to split up the datarecord in order to get the numbers (split up at every ";").

So maybe, another solution would be a MONTH-Table, with 32 columns (month and 1 to 31). the 1 to 31 columns would be tinyints and I would store the numbers in it.
I would have to make one select to get the data from each month and I would not have to split up the datarecord but could request the data per column (I use hibernate)

Does this last solution have any disadvantages I didnt think of? :-) Would you recommend another solution?

[EDIT]
Thanks for your help. This was the data structure before:

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;

and here did I now store the information for a whole month in:

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;

a query for the second table would be:

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;
}

to get data from the first table I use the same entry, but of course ClientsData instead of ClientsMonthlyInformation. You are correct, I could create a query to get 31-Datarecords, that means 31 Hibernate-Objects. I don't know why I thought that doing one select on 31 rows to get 31 objects would be bad.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫腻 2024-11-15 06:04:24

最多需要进行 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');

假设您希望以非规范化结构输出 - 并且绝对确定没有丢失/重复的日子)

have to do up to 31 selects to get the data for one month. As I do this very often, it stresses the database

Define often? How many days have you currently got? Unless it's more than 20 times per second there shouldn't be any measurable impact in the database.

Now I thought of writing the whole information (31 numbers) into a MONTH-table

That's a really dumb idea and is not going to solve the problem.

If you have to issue 31 selects to fetch a months data then you really need to learn more about querying databases.

Without knowing what your table structure is nor what the output format you require is, it's not possible to provide a specific solution, but you might consider:

 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');

(assuming you want the output in a denormalised structure - and are absolutely sure there are no missing/duplicate days)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文