优化和加速MySQL查询选择

优化和加速MySQL查询选择,mysql,select,query-optimization,rdbms,Mysql,Select,Query Optimization,Rdbms,我试图找出哪种方法是优化MySQL数据库上当前选择查询的最佳方法 我有两个关系为一对多的MySQL表。一个是user表,它包含唯一的用户列表,大约有22krows。一个是linedata表,该表包含每个用户的所有可能坐标,大约49000行 在这种情况下,我们可以假设两个表之间的外键是id值。对于用户表,id也是自动递增主键,而在linedata表中,它不是主键,因为同一用户可以有更多行 创建STMT结构 选择查询 例如,如果我为筛选单个用户添加了另一个WHERE条件,则选择查询将起作用。假设我只

我试图找出哪种方法是优化MySQL数据库上当前选择查询的最佳方法

我有两个关系为一对多的MySQL表。一个是
user
表,它包含唯一的用户列表,大约有22krows。一个是
linedata
表,该表包含每个用户的所有可能坐标,大约49000行

在这种情况下,我们可以假设两个表之间的外键
id
值。对于用户表,id也是自动递增主键,而在linedata表中,它不是主键,因为同一用户可以有更多行

创建STMT结构 选择查询 例如,如果我为筛选单个用户添加了另一个WHERE条件,则选择查询将起作用。假设我只想选择200用户,然后我得到了14秒的执行时间。如果我只选择第一批100个用户,大约7秒。但在只有datetime范围条件的情况下,加载似乎没有结束点。有什么建议吗

更新 在遵循Rick的建议之后,现在查询基准大约为14秒。下面的
解释扩展的

id,选择类型,表格,类型,可能的键,键,键长度,参考,行,过滤,额外 1,主,u,索引,主,主,4,空,21959100.00,空 1,PRIMARY,l,ref,id_timestamp_index,id_timestamp_index,4,u.id,14100.00,“使用索引条件” 2,“依赖子查询”,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,“未使用表”

我对表格的某些值做了一些更改:

其中,用户表中的
id
可以与linedata表中的
userId
连接。现在它们是整数了。我们将为用户表中的userId值设置字符串类型,因为它是一种长字符串标识符,如0000309ab2912b2fd34350d7e6c079846bb6c5e1f97d3ccb053d15061433e77a\u 0

因此,我们将在
用户
行数据
表中提供一个快速示例:

+-------+-----------+-----------+-------------------+--------+---+
|   id  | isActive  |   userId  |       name        | gender |age|
+-------+-----------+-----------+-------------------+--------+---+
|   1   |   1       |  x4by4d   |   john            | m      | 22|
|   2   |   1       |  3ub3ub   |   bob             | m      | 50|
+-------+-----------+-----------+-------------------+--------+---+



+-------+-----------+-----------+------+---+
|   id  | userId    |timestamp  |  x   | y |
+-------+-----------+-----------+------+----+
|   1   |   1       | somedate  |  30  | 10 |
|   2   |   1       | somedate  |  45  | 15 |
|   3   |   1       | somedate  |  50  | 20 |
|   4   |   2       | somedate  |  20  |  5 |
|   5   |   2       | somedate  |  25  | 10 |
+-------+-----------+-----------+------+----+
我在linedata表中添加了一个由
userId
timestamp
值组成的复合索引


如果我添加一个由
userId
+
时间戳
组成的复合主键,而不是将
linedata
表的ai id值作为主键,那么可能会发生这种情况?是否应该提高性能?

在讨论性能之前,我需要帮助您修复几个错误

首先,
'2018-02-28620:00:00.000Z'
在MySQL中不起作用。它必须是
'2018-02-28 20:00:00.000'
,并且需要对时区采取措施

然后,不要“在函数中隐藏列”。也就是说,
DATEDIFF(l.timestamp…
不能在
timestamp
上使用任何索引

因此,与其

    WHERE  DATEDIFF(l.timestamp, '2018-02-28T20:00:00.000Z') >= 0
      AND  DATEDIFF(l.timestamp, '2018-11-20T09:20:08.218Z') <= 0
CREATE TABLE `linedata` (
  `id` int(11) NOT NULL,
  `userId` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  ...
你是说

CREATE TABLE `linedata` (
  `id` int(11) NOT NULL  AUTO_INCREMENT,  -- (the id for `linedata`)
  `userId` int NOT NULL,   -- to link to the other table
  ...
  PRIMARY KEY(id)
...
然后,对于每个
用户
,可能会有多个

在那一点上,这个

    JOIN  linedata l  ON u.id=l.id
变成

    JOIN  linedata l  ON u.id=l.userid
现在,为了提高性能:
linedata
需要
索引(userid,timestamp)
——顺序如下

现在,考虑一下输出。您要求的行数最多为2200行,其中一列中可能有数百个“ts,x,y”串在一起。什么会收到这么多数据?它会窒息吗

GROUP_CONCAT
的默认限制为1024字节。这将允许大约50分。如果一个“用户”在9天内可以超过50个点,在运行查询之前考虑增加<代码> GROPY-CONTATAXMAXYLIN 。 要使其工作得更快,请按以下方式重新编写:

SELECT  u.id, u.isActive, u.userId, u.name, u.gender, u.age,
        ( SELECT  GROUP_CONCAT(CONCAT_WS(', ',timestamp, x, y)
                      ORDER BY timestamp ASC
                      SEPARATOR '; ')
        ) as linedata_0
    FROM  user u
    JOIN  linedata l  ON u.id = l.userid
    WHERE  l.timestamp >= '2018-02-28 20:00:00.000'
      AND  l.timestamp  < '2018-11-20 09:20:08.218';
选择u.id、u.isActive、u.userId、u.name、u.gender、u.age、,
(选择GROUP_CONCAT(CONCAT_WS(',',时间戳,x,y)
按时间戳订购ASC
分隔符“;”)
)作为linedata_0
来自用户u
在u.id=l.userid上连接linedata l
其中l.timestamp>=“2018-02-28 20:00:00.000”
和l.时间戳<'2018-11-20 09:20:08.218';
还有一件事。您可能希望能够通过
名称
查找用户;因此,添加
索引(名称)


噢,
userID的
VARCHAR(255)
到底是什么??ID通常是整数。

这涵盖了我要建议的大部分内容。注意,我认为OP包括了它们精确的表结构,只是
linedata
表中没有PK,而且
id
列实际上包含与
user
表中的
id
列相同的值。出于某种目的,
userId
看起来像一个替代标识符。很可能,您建议的
(userid,timestamp)
索引可以通过将
(id,timestamp)
生成主键来处理,因为不可能允许用户一次拥有多个位置。@WillemRenzema所说的是正确的。我没有表linedata的pk,但无论如何,我创建了一个名为id的ai pk。我将用户表的id(pk ai)与用户id值连接起来,该值现在也是整数,并且匹配正确。@Rick James感谢您的回答。我已经纠正了某些观点。。尤其是
personId
类型。我现在已经生成了一个与
user
表的唯一
id
对应的整数值。我认为不能正常工作的是您的查询建议,因为我只得到一行结果,对应于一个用户。理论上,我应该得到大约21k行,每个时间戳和坐标的串联。我想你错过了u.id的最后一组。我说得对吗?如果我加上它,获取所有数据的基准大约是15秒。我更新了
EXPLAIN
stmt.@UgoL-好的开始。但是b
CREATE TABLE `linedata` (
  `id` int(11) NOT NULL  AUTO_INCREMENT,  -- (the id for `linedata`)
  `userId` int NOT NULL,   -- to link to the other table
  ...
  PRIMARY KEY(id)
...
    JOIN  linedata l  ON u.id=l.id
    JOIN  linedata l  ON u.id=l.userid
SELECT  u.id, u.isActive, u.userId, u.name, u.gender, u.age,
        ( SELECT  GROUP_CONCAT(CONCAT_WS(', ',timestamp, x, y)
                      ORDER BY timestamp ASC
                      SEPARATOR '; ')
        ) as linedata_0
    FROM  user u
    JOIN  linedata l  ON u.id = l.userid
    WHERE  l.timestamp >= '2018-02-28 20:00:00.000'
      AND  l.timestamp  < '2018-11-20 09:20:08.218';