内部查询速度非常慢。这有什么问题?mySQL

内部查询速度非常慢。这有什么问题?mySQL,mysql,subquery,distinct,Mysql,Subquery,Distinct,我有一个^join,它自己运行得非常好。打开行结果并开始循环后,我将运行第二个查询,从另一个表中执行计数和日期信息: SELECT * FROM grants INNER JOIN people on grants.volID=people.vol_id INNER JOIN org on grants.orgID=org.orgid order by yearStart DESC 我需要第一次拉取的数据来获得ORID,这就是为什么我要一次一个地检查它们 SELECT

我有一个^join,它自己运行得非常好。打开行结果并开始循环后,我将运行第二个查询,从另一个表中执行计数和日期信息:

SELECT * 
FROM grants 
    INNER JOIN people on grants.volID=people.vol_id 
    INNER JOIN org on grants.orgID=org.orgid 
order by yearStart DESC
我需要第一次拉取的数据来获得ORID,这就是为什么我要一次一个地检查它们

SELECT COUNT(Distinct Event_ID) as ME, MAX(Sample_Date) as MaxD 
FROM results where orgid=%d 
如果没有将二次查询推送到组织中,它将以非常快的速度遍历大约230条记录。它减慢到接近20秒!我没有正确地建立计数吗?结果表大约有100000条记录,但我用其他查询处理了这个问题,结果并不是这样的!如果有帮助的话,我如何子查询这个


谢谢你的洞察力

假设results.orgid被索引以排除该问题

如果您使用连接以便MySQL能够进行优化,事情通常会好得多。子查询的性能可能很差

如果我正确理解您的关系,请尝试以下方法:

so it runs like this
Query 1
while($row = mysql_fetch_assoc($result)){
 Query 2
 while($row1 = mysql_fetch_assoc($result1)){
 get some data from 2
 } //close 2
 get some data from 1 and merge with 2
 } //close 1

不要忘记将grants.grantid替换为实际的grants PK列。

要找出查询中的性能瓶颈,首先应该使用数据库的解释功能,这样它就可以告诉您它在做什么

听起来您可能没有正确设置某些索引,导致每次循环第一次连接查询的结果时都会扫描不必要的行。检查方法如下例所示:

首先我有一个测试表

SELECT grants.*, org.*, COUNT(Distinct Event_ID) as ME, MAX(Sample_Date) as MaxD
FROM grants 
    INNER JOIN people on grants.volID=people.vol_id
    INNER JOIN org on grants.orgID=org.orgid
    LEFT JOIN results ON results.orgid=org.orgid
GROUP BY grants.grantid #whatever your grants PK is
ORDER BY yearStart DESC
接下来我添加几行

mysql> desc test_table;
+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| id          | int(11)     | NO   | PRI | NULL    | auto_increment |
| name        | varchar(64) | YES  |     | NULL    |                |
| description | text        | YES  |     | NULL    |                |
| published   | datetime    | YES  |     | NULL    |                |
| updated     | datetime    | YES  |     | NULL    |                |
| status      | tinyint(1)  | YES  |     | NULL    |                |
+-------------+-------------+------+-----+---------+----------------+
6 rows in set (0.02 sec)

mysql> show indexes from test_table;
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table      | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_table |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.01 sec)

mysql> select count(1) from test_table;
+----------+
| count(1) |
+----------+
|        0 |
+----------+
1 row in set (0.02 sec)
接下来,我使用数据库中的EXPLAIN功能来分析我的查询

mysql> INSERT INTO test_table (name, description, published, status) VALUES ('name1','description 1 goes here',now(),1),('name2','description 2 goes here',now(),1),('name3', 'description 3 goes here', now(),1);
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select name, description from test_table where status = 1;
+-------+-------------------------+
| name  | description             |
+-------+-------------------------+
| name1 | description 1 goes here |
| name2 | description 2 goes here |
| name3 | description 3 goes here |
+-------+-------------------------+
3 rows in set (0.01 sec)
您可以看到它正在扫描3行以查找记录。我怀疑您的数据库正在扫描第二个查询的所有10万行,即您迭代的每一行。这意味着,如果在第一次查询中有100个结果,则有1000万行扫描(100*100K)。您希望rows列尽可能接近1,这意味着它将使用索引查找更快的行

现在,我创建了一个索引,并在WHERE子句中包含了我希望包含的列(我将按顺序添加它们,注意每次都不需要全部使用)

接下来,我再次尝试解释,看看数据库是如何使用索引的,只扫描了一行。您应该优化索引以获得类似的结果

mysql> CREATE INDEX idx_so_example ON test_table (name, description (255), status);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0
对于您的数据库,我将在第二个查询中的这3列上添加一个复合索引,假设“results”是基于您的问题的实际表名

mysql> EXPLAIN SELECT name, description, status FROM test_table WHERE name = 'name1' AND status = 1;
+----+-------------+------------+------+----------------+----------------+---------+-------+------+-----------------------+
| id | select_type | table      | type | possible_keys  | key            | key_len | ref   | rows | Extra                 |
+----+-------------+------------+------+----------------+----------------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | test_table | ref  | idx_so_example | idx_so_example | 195     | const |    1 | Using index condition |
+----+-------------+------------+------+----------------+----------------+---------+-------+------+-----------------------+
1 row in set (0.01 sec)

还有一个建议:您的命名约定应该与字段一致,否则您的数据库将成为记忆和编码的噩梦。选择一个标准并坚持使用它,这样如果使用EventId、SampleDate、OrgId great或event_id、sample_date、org_id,但要标准化所有列名和约定,以便在以后尝试查询数据时代码中的语法错误更少。

该循环发生在哪种编程语言中?当然,230很快。每个都有400多个。您是否有一个
show create table xxx
或两个要共享的表?是否可以打开声纳进行索引策略ID是否已索引?如果orgid没有在子查询上建立索引,那么它必须读取每一行。否则,它可能只是子查询。MySQL没有很好地优化子查询…如果可能的话,最好是根据结果表进行连接,然后根据您的授权行ID进行分组,以防止重复。orgid在子查询中没有索引。好的,那么添加一个索引,如果仍然很慢,试着使用我在回答中提到的连接——假设我正确理解了这些关系。迈克,谢谢你的深入回复。我正努力坚持下去。所以我想我需要结合您的概念,为这些结果列编制索引,然后重写我的查询以运行连接,就像Kevin在下面提到的那样。他在开场白中写道,他只会在假设我的结果是索引的情况下工作。通过在mySQL中运行上面的代码行。。。“idx_某些_名称”。我需要在下面的查询中引用它吗?或者我可以只调用列名吗?为结果表中的三列编制索引确实大大提高了速度!伟大的威尔想出了答案……很高兴能帮上忙。我正在扩展的一个应用程序最初是在MySQL 3.23上构建的,在添加了慢速查询日志后,我了解到,如果稍后当它变得庞大(数亿行)时尝试索引,索引可能需要数小时甚至数天。今天,我们不那么担心了,但拯救我们的是使用Percona版本的MySQL和异步索引,这样您就可以解释和索引(尝试/错误),而无需等待数小时到数天来解决瓶颈问题。我认为MySQL的更新版本现在提供了类似的但是要考虑的东西。祝你好运这是向我展示一个使用左连接的更好查询的要点。答案是索引。谢谢你们两个!
mysql> EXPLAIN SELECT name, description, status FROM test_table WHERE name = 'name1' AND status = 1;
+----+-------------+------------+------+----------------+----------------+---------+-------+------+-----------------------+
| id | select_type | table      | type | possible_keys  | key            | key_len | ref   | rows | Extra                 |
+----+-------------+------------+------+----------------+----------------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | test_table | ref  | idx_so_example | idx_so_example | 195     | const |    1 | Using index condition |
+----+-------------+------------+------+----------------+----------------+---------+-------+------+-----------------------+
1 row in set (0.01 sec)
CREATE INDEX idx_some_name ON results (Event_ID, Sample_Date, orgid);