Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.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_Database_Performance_Select_Query Performance - Fatal编程技术网

提高MySQL选择查询的执行速度

提高MySQL选择查询的执行速度,mysql,database,performance,select,query-performance,Mysql,Database,Performance,Select,Query Performance,我有两个MySQL表,其中有数百万行,我正在尝试对这两个表中的get-specific-data列执行查询选择。尽管我的第一个良好预期是,查询选择的执行也需要几秒钟(大约5秒钟)的时间,索引也应用于WHERE条件 为2个MySQL表创建语句: 如您所见,这两个表都有一个AI主键和外键,它们之间匹配为一对一关系(T1\u id和T2\u id)。我们有一个索引应用于T1,用于T1_val4的日期时间格式 选择查询 正如您所注意到的,我为索引指定了一个提示,以便告诉MySQL对datetime列使用

我有两个MySQL表,其中有数百万行,我正在尝试对这两个表中的get-specific-data列执行查询选择。尽管我的第一个良好预期是,查询选择的执行也需要几秒钟(大约5秒钟)的时间,索引也应用于WHERE条件

为2个MySQL表创建语句: 如您所见,这两个表都有一个AI主键外键,它们之间匹配为
一对一关系
T1\u id
T2\u id
)。我们有一个索引应用于
T1
,用于
T1_val4
日期时间格式

选择查询 正如您所注意到的,我为索引指定了一个提示,以便告诉MySQL对datetime列使用该特定索引。实际上,如果我将WHERE条件下的datetime范围扩展到几个小时。。例如,
在“2016-02-18 15:00:00”和“2016-02-18 23:59:59”之间执行时间增长到50/100秒。也许我在逻辑上遗漏了什么

解释输出 EXPLAIN输出用复合索引更新 (根据@O.Jones的建议)

ix_rlf
T1_val4
T1_val9
T1_val5
ix_cc是@Tom Shir为T2建议的复合索引,由
T2_id
T2_val1
T2_val2
T2_val3
组成

查询执行计划可视化模式 (以2小时为间隔,在本例中,查询结果约为6632行,执行时间为6/7秒)


从您的
GROUP By
子句中省略
T1_val4
就是在利用MySQL的非标准扩展。你可能会得到不想要的结果。请看这个

通常,对类似日期时间的列使用
BETWEEN
是个坏主意,因为它处理范围结束条件很差。如果我是你,我会写这个

WHERE T1_val4 >= '2016-02-18 15:00:00' AND T1_val4 < '2016-02-18 17:00:00'
因为您使用的是InnoDB,所以不必在复合索引中包含主键


这应该快一点。但是,您仍然要求MySQL检索和索引一万行,这实际上是真正的工作。

这是您的带有表前缀的查询:

SELECT
        T1.T1_val5,
        T2.T2_val1,
        T2.T2_val2,
        T2.T2_val3,
        T1.T1_val9,
        COUNT(T2.T2_val1) AS cnt,
        T1.T1_val4 
    FROM
        T1 
    INNER JOIN
        T2.T2 
            ON T1.T1_id = T2.T2_id 
    WHERE
        T1.T1_val4 BETWEEN '2016-02-18 15:00:00' AND '2016-02-18 16:59:59' 
    GROUP BY
        T2.T2_val1,
        T2.T2_val2,
        T2.T2_val3,
        T1.T1_val9,
        T1.T1_val5 
    ORDER BY
        T1.T1_val4 ASC
我相信您可以通过使用正确的索引来提高其性能。 我通过一个用于我自己的查询的数据库运行了您的查询,该数据库建议使用以下索引:

ALTER TABLE `T1` ADD INDEX `T1_index_1` (`T1_id`, `T1_val4`);
ALTER TABLE `T2` ADD INDEX `T2_index_1` (`T2_id`, `T2_val1`, `T2_val2`, `T2_val3`);
另外,请发布解释计划,因为它可以帮助更好地理解MySQL当前使用的索引


另一个建议-删除您添加的提示。通常,MySQL会比我们更了解如何优化查询。

请阅读本文,请特别注意有关查询性能的部分。请您的问题向我们展示
解释
输出和其他相关信息。顺便说一句,您的
分组依据
子句还需要提到
T1_val4
,您的邮戳栏。您说得对!给我几分钟,我将添加解释输出。
innodb\u buffer\u pool\u size的值是多少?您有多少RAM?对于
innodb\u buffer\u pool\u size
而言,它是6123683840请注意,
ix\u cc
未被选中。无论如何,
PRIMARY
也差不多。谢谢@O.Jones的回复。我正在阅读我收到的两个答案。你能确切地解释一下为什么只索引
T1
应该比@Tom Shir写的
T2
更好吗?在性能方面应该略有不同?我已经尝试添加了您为
T1
建议的复合索引,我已经替换了中间条件,并且我还将
T1\u val4
纳入了组中。但是在这些更改之后,执行性能保持不变。我不建议索引
T2
,因为您的
EXPLAIN
输出表示您的查询只查看了几行,而且您通过其主键访问它,并且没有
WHERE
条件。添加复合索引后,
解释
会告诉你什么?更好的是:
其中T1_val4>='2016-02-18 15:00:00'和T1_val4<'2016-02-18 15:00:00'+间隔2小时
@UgoL-间隔
模式对性能没有帮助-一定是同时发生了其他事情。(10倍的加速通常可以追溯到缓存。)fwiw,对于优化
T1_val4
上范围扫描的索引,该列必须位于索引列列表的第一位。此外,在InnoDB中,主键位于第一位的索引与表本身的结构是冗余的。您能否解释一下为什么范围列应该位于第一位(可能还包括一个引用链接)?如果是这种情况,那么这意味着您不能创建一个索引,其中ON子句中的列和范围扫描都将用于优化同一查询?是理解查询优化的好资源。MySQL索引具有有序的BTREE结构。因此,当查询调用某列中的连续值范围时,如果该列位于第一列,则查询计划器可以随机访问第一个符合条件的条目的索引,然后按顺序扫描到最后一个条目。谢谢。我已经阅读了过去的那些文章,看到这个页面指定先为相等设置索引,然后才为范围设置索引。当等式为col1=col2(就像通常在join-ON子句中发生的那样)而不是col1=const时,情况会有所不同吗?
+-------+---------------+-----------+-----------+------------------------------+-----------+---------------+-----------+-----------+---------------------------------------------------------------+
|   ID  |   SELECT_TYPE |   TABLE   |   TYPE    |   POSSIBLE_KEYS              |   KEY     |   KEY_LEN     |   REF     |   ROWS    |       EXTRA                                                   |
+-------+---------------+-----------+-----------+------------------------------+-----------+---------------+-----------+-----------+---------------------------------------------------------------+
|   1   |   SIMPLE      |   T1      |   range   |   "PRIMARY,ix_rlf"           |   ix_rlf  |      5        |   NULL    |   10906   |   "Using where; Using index; Using temporary; Using filesort" |
+-------+---------------+-----------+-----------+------------------------------+-----------+---------------+-----------+-----------+---------------------------------------------------------------+
|   1   |   SIMPLE      |   T2      |   eq_ref  |   "PRIMARY,ix_cc"            |   PRIMARY |      4        |   T1_id   |   1       |     NULL                                                      |
+-------+---------------+-----------+-----------+------------------------------+-----------+---------------+-----------+-----------+---------------------------------------------------------------+
WHERE T1_val4 >= '2016-02-18 15:00:00' AND T1_val4 < '2016-02-18 17:00:00'
 T1_val4, T1_val9, T1_val5
SELECT
        T1.T1_val5,
        T2.T2_val1,
        T2.T2_val2,
        T2.T2_val3,
        T1.T1_val9,
        COUNT(T2.T2_val1) AS cnt,
        T1.T1_val4 
    FROM
        T1 
    INNER JOIN
        T2.T2 
            ON T1.T1_id = T2.T2_id 
    WHERE
        T1.T1_val4 BETWEEN '2016-02-18 15:00:00' AND '2016-02-18 16:59:59' 
    GROUP BY
        T2.T2_val1,
        T2.T2_val2,
        T2.T2_val3,
        T1.T1_val9,
        T1.T1_val5 
    ORDER BY
        T1.T1_val4 ASC
ALTER TABLE `T1` ADD INDEX `T1_index_1` (`T1_id`, `T1_val4`);
ALTER TABLE `T2` ADD INDEX `T2_index_1` (`T2_id`, `T2_val1`, `T2_val2`, `T2_val3`);