1

我想将数据存储在 MySQL 中并根据当天进行查询。我想知道这样做的最佳做法是什么。

我想存储每天的数据总数,因此查询总数据会很快。我想按如下方式对我的表进行建模:

TotalsByCountry
- Year
- Month
- Day
- countryId
- totalNumber

当我查询特定日期和特定国家/地区的总计时,我将基于 4 列查询表,即年、月、日和国家 ID。

我想知道这是否是一个好的做法,或者有更好的方法,比如使用一列保存月、日和年的数据,并只查询两列,即日期时间列和国家 ID。

需要您帮助选择正确的表格建模方式。我还想制作另一个表格来存储基于性别的总数,所以也要考虑到这一点。

数据需要经常访问,也许是实时的,因为我想实时显示数据的变化。我将在 asp.net 中开发 Web 应用程序,并可能使用 Web 套接字来创建将实时更新用户数据的持续连接。所以当数据发生变化时,会实时反映在用户网页上。这就是为什么我需要一个可以用于许多查询的表建模。我将使用缓存几秒钟,因此它需要对 db 造成太大压力。

我希望我提供了足够的信息,如果没有,请发表评论,我会回复。

4

2 回答 2

3

使用三个单独的列来存储日期(年/月/日)的每个单独元素会在插入性能和磁盘空间方面给数据库增加不必要的开销。

您要做的只是有一个单独的DATETIME列来存储日期和时间,并在(countryId, datetime_col).

即使您想根据特定的日期或月份查询所有行,MySQL 仍然能够利用 DATETIME 字段上的索引,前提是您以正确的方式编写查询并确保永远不会包装DATETIME 列执行条件检查时在函数内。

以下是编写查询的方法,以便它仍然能够利用索引:

-- Get the sum of totalNumber of all rows based on current day
-- where countryId = 1

SELECT SUM(totalNumber) AS totalsum
FROM   tbl
WHERE  countryId = 1 AND
       datetime_col >= CAST(CURDATE() AS DATETIME) AND
       datetime_col <  CAST(CURDATE() + INTERVAL 1 DAY AS DATETIME)

通过在裸 DATETIME 列上进行比较,查询仍然是 sargable(即能够利用索引范围扫描)并且 MySQL 将能够使用索引来快速查找行。

另一方面,如果您尝试将 DATETIME 列包装在函数中以进行比较:

-- Get the sum of totalNumber of all rows based on current day
-- where countryId = 1

SELECT SUM(totalNumber) AS totalsum
FROM   tbl
WHERE  countryId = 1 AND
       DATE(datetime_col) = CURDATE()

...这将是非常低效的,因为DATE()包装列的函数有效地将查询呈现为不可分割,并且您设置的包含 DATETIME 列的任何类型的索引都不会被使用。

您还可以有效地查询当月所有行的总和:

-- Get the sum of totalNumber of all rows based on current month
-- where countryId = 1

SELECT SUM(totalNumber) AS monthsum
FROM   tbl
WHERE  countryId = 1 AND
       datetime_col >= CAST(CONCAT(YEAR(NOW()), '-', MONTH(NOW()), '-01') AS DATETIME) AND
       datetime_col <  CAST(CONCAT(YEAR(NOW()), '-', MONTH(NOW()), '-01') AS DATETIME) + INTERVAL 1 MONTH

本年度内:

-- Get the sum of totalNumber of all rows based on current year
-- where countryId = 1

SELECT SUM(totalNumber) AS yearsum
FROM   tbl
WHERE  countryId = 1 AND
       datetime_col >= CAST(CONCAT(YEAR(NOW()), '-01-01') AS DATETIME) AND
       datetime_col <  CAST(CONCAT(YEAR(NOW()), '-01-01') AS DATETIME) + INTERVAL 1 YEAR
于 2012-07-15T23:05:32.250 回答
1

我的论点是:如果您想快速进行数据库查找,则需要使用索引的良好构建查询。您的方法需要 4 个索引(这意味着插入速度较慢),使用单个日期列只需要两个索引,如果您需要搜索日期范围,查询的复杂性也会增加。

于 2012-07-15T22:23:38.913 回答