Mysql 具有百万行的数据库表
例如,我有一些gps设备,每秒钟向我的数据库发送信息 因此,1个设备在mysql数据库中使用这些列创建一行(8) id=12341日期=22.02.2018时间=22:40 经度=22.236558789经度=78.9654582设备ID=24名称=设备名称someinfo=ASDADADADASD 因此,在1分钟内,它创建了60行,在24小时内,它创建了864000行 1个月(31天)2678400行 因此,1台设备每月在my db表中创建260万行(每个月删除记录) 因此,如果有更多的设备,将有260万*的设备数量 所以我的问题是这样的: 问题1:如果我从php中进行类似的搜索(仅针对当天和1台设备) 最大可能结果为86400行Mysql 具有百万行的数据库表,mysql,sql,database,Mysql,Sql,Database,例如,我有一些gps设备,每秒钟向我的数据库发送信息 因此,1个设备在mysql数据库中使用这些列创建一行(8) id=12341日期=22.02.2018时间=22:40 经度=22.236558789经度=78.9654582设备ID=24名称=设备名称someinfo=ASDADADADASD 因此,在1分钟内,它创建了60行,在24小时内,它创建了864000行 1个月(31天)2678400行 因此,1台设备每月在my db表中创建260万行(每个月删除记录) 因此,如果有更多的设备,
它会使我的服务器过载太多吗 问题2:限制为5小时(18000行),这对数据库来说是个问题,还是像第一个示例那样加载服务器或更少
SELECT * FROM TABLE WHERE date='22.02.2018' AND deviceID= '24' LIMIT 18000
问题3:如果我只显示来自db的1个结果,它会使服务器过载吗
SELECT * FROM TABLE WHERE date='22.02.2018' AND deviceID= '24' LIMIT 1
这是否意味着,如果我有数百万行,1000行将加载相同的服务器,如果我只显示一个结果请阅读您的问题,对我来说答案是
只需为纬度和经度创建一个单独的表,并将您的ID设置为外键并将其保存。在不知道您要运行的确切查询的情况下,我只能猜测最佳结构。话虽如此,您应该以每行使用最少字节数的最佳类型为目标。这将使您的查询更快 例如,您可以使用以下结构:
create table device (
id int primary key not null,
name varchar(20),
someinfo varchar(100)
);
create table location (
device_id int not null,
recorded_at timestamp not null,
latitude double not null, -- instead of varchar; maybe float?
longitude double not null, -- instead of varchar; maybe float?
foreign key (device_id) references device (id)
);
create index ix_loc_dev on location (device_id, recorded_at);
如果包含精确的查询(命名列),我们可以为它们创建更好的索引
因为您的查询选择性可能不好,所以您的查询可能会运行全表扫描。在本例中,我进一步使用了最小的列数据类型,因此速度更快:
create table location (
device_id tinyint not null,
recorded_at timestamp not null,
latitude float not null,
longitude float not null,
foreign key (device_id) references device (id)
);
没有比这更小的了。数百万行不是问题,这是SQL数据库设计用来处理的,如果您有一个设计良好的模式和良好的索引 使用合适的类型 不要将日期和时间存储为单独的字符串,而是将它们存储为单个或单独的
date
和time
类型。请参阅下面的索引,了解有关使用哪一个的更多信息。这不仅更加紧凑,允许索引,更快的排序,而且无需进行转换
同样,请确保使用适当的纬度和经度。您可能希望使用以确保精度
因为您将要存储数十亿行,所以请确保将a用作主键。一个普通整数只能达到20亿左右
将重复的数据移动到另一个表中。
与其在每一行中存储有关设备的信息,不如将其存储在单独的表中。然后只在日志中存储设备的ID。这将减少存储大小,并消除由于数据重复而导致的错误。请确保将设备ID声明为外键,这将提供和索引
添加索引
是什么让数据库能够非常、非常高效地搜索数百万或数十亿行。确保经常使用的行上有索引,例如时间戳
date
和deviceID
上缺少索引可能是查询速度如此缓慢的原因。如果没有索引,MySQL必须查看数据库中的每一行,称为索引。这就是为什么查询速度如此之慢,缺少索引
您可以发现您的查询是否正在使用索引
datetime
或time
+date
?
通常情况下,最好将日期和时间存储在一列中,通常称为created\u at
。然后,您可以使用date
仅获取日期部分,如下所示
select *
from gps_logs
where date(created_at) = '2018-07-14'
有个问题。问题是索引如何工作。。。或者不要。由于函数调用,where date(created_at)='2018-07-14'
将不使用索引。MySQL将在每一行上运行date(创建时间)
。这意味着要进行性能破坏性的全表扫描
您可以通过只使用datetime
列来解决此问题。这将使用索引,而且效率很高
select *
from gps_logs
where '2018-07-14 00:00:00' <= created_at and created_at < '2018-07-15 00:00:00'
但它更多地涉及到一个单独的日期
和时间
select *
from gps_logs
where (created_date = '2018-07-12' and created_time >= '10:00:00')
or (created_date = '2018-07-13' and created_time < '10:00:00');
有了这么多的数据,您将需要严重依赖分组依据
和相关的总和
,计数
,最大
,最小
等等
避免选择*
如果必须检索86400行,那么从数据库中简单地获取所有数据的成本可能会很高。通过只获取所需的列,可以显著加快速度。这意味着使用select only,您需要的是而不是select*
把它们放在一起。
在PostgreSQL中
PostgreSQL中的模式应该是这样的
create table gps_devices (
id serial primary key,
name text not null
-- any other columns about the devices
);
create table gps_logs (
id bigserial primary key,
gps_device_id int references gps_devices(id),
created_at timestamp not null default current_timestamp,
latitude numeric(12,9) not null,
longitude numeric(12,9) not null
);
create index timestamp_and_device on gps_logs(created_at, gps_device_id);
create index date_and_device on gps_logs((created_at::date), gps_device_id);
查询通常只能对每个表使用一个索引。由于您将同时搜索时间戳和设备ID,因此大量时间戳和设备
组合索引时间戳和设备ID
日期和设备是一样的,但它只是时间戳日期部分的部分索引。这将使在哪里创建_at::date='2018-07-12'和gps_设备_id=42
非常有效
select *
from gps_logs
where '2018-07-14 00:00:00' <= created_at and created_at < '2018-07-15 00:00:00'
在MySQL中
非常相似,但没有部分索引。因此,您需要在where
子句中始终使用在处创建的裸,或者切换到单独的日期
和时间
类型。我可以向您推荐的最佳方法是使用时间序列数据库
select gps_device_id, count(id) as num_entries, created_at::date as day
from gps_logs
group by gps_device_id, day;
gps_device_id | num_entries | day
---------------+-------------+------------
1 | 29310 | 2018-07-12
2 | 23923 | 2018-07-11
2 | 23988 | 2018-07-12
create table gps_devices (
id serial primary key,
name text not null
-- any other columns about the devices
);
create table gps_logs (
id bigserial primary key,
gps_device_id int references gps_devices(id),
created_at timestamp not null default current_timestamp,
latitude numeric(12,9) not null,
longitude numeric(12,9) not null
);
create index timestamp_and_device on gps_logs(created_at, gps_device_id);
create index date_and_device on gps_logs((created_at::date), gps_device_id);
create table gps_devices (
id int primary key auto_increment,
name text not null
-- any other columns about the devices
);
create table gps_logs (
id bigint primary key auto_increment,
gps_device_id int references gps_devices(id),
foreign key (gps_device_id) references gps_devices(id),
created_at timestamp not null default current_timestamp,
latitude numeric(12,9) not null,
longitude numeric(12,9) not null
);
create index timestamp_and_device on gps_logs(created_at, gps_device_id);