Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.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 sql计数结果查询与连接性能_Mysql_Sql_Performance_Join_Count - Fatal编程技术网

Mysql sql计数结果查询与连接性能

Mysql sql计数结果查询与连接性能,mysql,sql,performance,join,count,Mysql,Sql,Performance,Join,Count,我有以下表格作为示例 t1 (20.000 rows, 60 columns, primary key t1_id) t2 (40.000 rows, 8 columns, primary key t2_id) t3 (50.000 rows, 3 columns, primary key t3_id) t4 (30.000 rows, 4 columns, primary key t4_id) sql查询: SELECT COUNT(*) AS count FROM (t1) JOIN t2

我有以下表格作为示例

t1 (20.000 rows, 60 columns, primary key t1_id)
t2 (40.000 rows, 8 columns, primary key t2_id)
t3 (50.000 rows, 3 columns, primary key t3_id)
t4 (30.000 rows, 4 columns, primary key t4_id)
sql查询:

SELECT COUNT(*) AS count FROM (t1)
JOIN t2 ON t1.t2_id = t2.t2_id
JOIN t3 ON t2.t3_id = t3.t3_id
JOIN t4 ON t3.t4_id = t4.t4_id
我已经在影响连接的列上创建了索引,例如在t1.t2_id和外键上(如果需要)。查询速度慢600毫秒,如果我放入where子句,例如where t1.column10=1,其中column10没有索引,查询速度就会慢得多。我对select*和LIMIT的查询速度很快,我无法理解计数行为。有解决办法吗

编辑:添加解释SQL

id  select_type     table   type    possible_keys   key     key_len     ref  rows   Extra
1   SIMPLE          t4      index   PRIMARY     user_id     4           NULL  5259  Using index
1   SIMPLE          t2      ref     PRIMARY,t4_id   t4_id   4        t4.t4_id   1   Using index
1   SIMPLE          t1      ref     t2_id         t2_id     4        t2.t2_id   1   Using index
1   SIMPLE          t3      ref     PRIMARY     PRIMARY     4        t2.t2_id   1   Using index
其中,user_id是t4表的一列

编辑:我从innodb改为myisam,速度有所提高,特别是如果我加入where子句。但是我仍然有100-150毫秒的时间。我想在我的应用程序中计算的原因是,对于处理搜索表单的用户来说,他希望通过ajax获得多少结果。在这方面可能有更好的解决方案,例如创建一个每一小时更新一次的临时表?

count迭代整个结果集,不依赖于索引。使用EXPLAIN Analysis检查查询的执行方式

select+limit不会迭代整个结果集,因此它的计数速度更快*性能较慢:您使用的是InnoDB引擎吗?见:

主要信息似乎是:InnoDB使用集群主键,因此主键与行一起存储在数据页中,而不是单独的索引页中

因此,一种可能的解决方案是创建一个单独的索引,并通过SQL查询中的USE index命令强制使用它。查看此评论以获取示例使用情况报告:

关于WHERE问题,如果将条件放入JOIN子句中,查询将执行得更好,如下所示:

SELECT COUNT(t1.t1_id) AS count FROM (t1)
JOIN t2 ON (t1.column10 = 1) AND (t1.t2_id = t2.t2_id)
JOIN t3 ON t2.t3_id = t3.t3_id
JOIN t4 ON t3.t4_id = t4.t4_id

正如查询计划中所述,由于只扫描索引,计数查询速度更快。您提到的查询只包含索引列,这就是为什么在执行期间不需要接触物理数据-所有查询都是在索引上执行的。当您添加一些由未被索引的列组成的附加子句,或者以防止索引使用的方式进行索引时,需要按物理地址访问存储在堆表中的数据,这非常缓慢

编辑: 另一件重要的事情是,这些都是PK,所以它们是独一无二的。优化器选择对第一个索引执行索引范围扫描,并且只检查后续索引中是否存在键,这就是计划声明只返回一行的原因

编辑2:
Thx对J.Bruni来说,事实上,这是聚集指数co,以上并不是全部事实。可能对第一个表进行了完全扫描,并随后进行了三次索引访问以确认FK的存在。

请使用MySQL命令EXPLAIN进行查询,并告知结果。感谢添加的解释。为了性能起见,允许进行一些折衷,如反规范化。例如,您可以做的是保持每个主行中的详细信息行数。所以,如果您的表构建了一个4层树,那么每个节点都会在每个层上保留其子节点的数量。我让更新变得更难你可以使用一些存储过程,但是计数可以用于查询一个表。如果你在数据库中放置一个样本,会更容易。不是这样,当计算行数时,DBMS可以执行仅索引扫描,甚至不接触堆表——当然是在特定情况下。我不清楚如何执行仅索引扫描来计算通过连接表获得的结果集中的行数。在这种特殊情况下,这是很棘手的。:-请注意,只涉及PK,因此我们可以确保它们是唯一的。我们所要做的就是对第一个表T4(最小的表)进行索引范围扫描,并检查键是否存在于后续的索引中—只是索引访问,而不是因为唯一性而进行范围扫描。这就是为什么计划声明在后续操作中只返回一行。这是适当的索引和出色的优化器的威力。不是真的,只有外部连接有区别,内部连接没有区别。优化器可能会选择首先筛选T1表。我使用了COUNTt1.T1_id,它没有区别。在连接中加入where子句会稍微加快速度,但主要问题仍然是..在研究过程中发现了有趣的资源。值得一看:实际上,我改成了myisam,并优化了我的查询,每次只进行必要的连接。现在,对于表大小,每个计数查询的平均时间为100ms,这对我来说仍然很慢。另请参见我在帖子中的编辑:我添加了一个真实数据库的示例!我添加了一个真实数据库的示例!