Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 具有百万行的数据库表_Mysql_Sql_Database - Fatal编程技术网

Mysql 具有百万行的数据库表

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万行(每个月删除记录) 因此,如果有更多的设备,

例如,我有一些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行
它会使我的服务器过载太多吗

问题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);