优化MySQL查询的运行时间

优化MySQL查询的运行时间,mysql,yii,Mysql,Yii,有一个表users,主键为user_id,索引列为verified。 另一个表user_profile将PK作为profile_id,将FK作为user_id,并具有一个列名 现在,我需要找到所有已验证的用户及其姓名。所以我需要在user_id上连接这两个表- 查询变为- select p.name from user_profile p inner join user u on p.user_id = u.user_id where u.verified = 1; 配置文件表中有700000

有一个表users,主键为user_id,索引列为verified。 另一个表user_profile将PK作为profile_id,将FK作为user_id,并具有一个列名

现在,我需要找到所有已验证的用户及其姓名。所以我需要在user_id上连接这两个表-

查询变为-

select p.name from user_profile p inner join user u on p.user_id = u.user_id
where u.verified = 1;
配置文件表中有700000条记录,用户表中有相同数量的记录。上面的查询需要13秒才能运行。请让我知道,如何优化运行时间

MySQL版本5.5,YII

编辑
--

--表
tbl\u用户的表结构
EXPLAIN SELECT的输出-我编写了与上面相同的查询,但将999替换为1,并使用列状态而不是验证,这相当于问题语句

EXPLAIN SELECT p.firstname
FROM tbl_profile p
INNER JOIN tbl_user u ON p.user_id = u.id
WHERE u.status =999
+----+-------------+-------+------+----------------+---------+---------+-------------+--------+-------------+
| id | select_type | table | type | possible_keys  | key     | key_len | ref         | rows   | Extra       |
+----+-------------+-------+------+----------------+---------+---------+-------------+--------+-------------+
|  1 | SIMPLE      | u     | ref  | PRIMARY,status | status  | 4       | const       | 313333 | Using index |
|  1 | SIMPLE      | p     | ref  | user_id        | user_id | 4       | newone.u.id |      1 |             |
+----+-------------+-------+------+----------------+---------+---------+-------------+--------+-------------+

建议1

(用户id,名字)
上添加索引将提高此特定查询的效率:

ALTER TABLE tbl_profile
  ADD INDEX user_id_first_name_IX             -- just a name for the index
    (user_id, first_name) ; 
但是,如果您也有类似的查询,在其中选择其他列,您将需要更多这样的索引。在表中添加5-10个索引并不太糟糕(这只会使插入速度减慢一点),但添加太多的索引最终将是有害的


建议2

如果每个用户最多有一个配置文件,则不需要在表
配置文件
中有一个自动递增的
id
。我建议您删除该列,并将
user\u id
作为主键。我也会将其作为外键:

ALTER TABLE tbl_profile
  DROP PRIMARY KEY,
  DROP COLUMN id,
  ADD CONSTRAINT profile_PK
    PRIMARY KEY (user_id),
  ADD CONSTRAINT user_profile_FK 
    FOREIGN KEY (user_id)
    REFERENCES tbl_user (id) ; 

这比建议1要好得多,因为您基本上将
user\u id
作为表的聚集索引。对于此表上的联接,任何使用
user\u id
的查询都可以使用此(主索引和聚集索引)。

您可以通过将条件移动到联接的
on
子句中来获得性能改进:

select p.name
from user_profile p
join user u on p.user_id = u.user_id and u.verified = 1;
之所以它的性能更好,是因为
WHERE
子句是在所有行都被联接之后计算的,它是结果集上的一个过滤器。但是,
上的
条件是在进行连接时计算的,因此数据库可能需要处理更少的行,从而需要更少的内存/资源


除此之外,我看不到您还能做什么。

表上有哪些索引?添加两个表的
CREATE TABLE
语句和
EXPLAIN SELECT…
的输出一个用户可以有多个配置文件吗?不,一个用户只有一个配置文件,我想你会建议加入它们并创建一个表吗?实际上,用户表只用于登录,而另一个表有与配置文件相关的数据。不,我已经添加了我的建议作为答案。不知道Yii是否会对这一变化有任何问题。一些ORM/框架在没有自动递增PKs的表上存在问题。我不知道为什么会出现向下投票,我必须尝试每个建议,看看哪个运行得最快。尝试它们是非常明智的。通常,这是处理查询的最快和最好的方法-进行一些更改并比较时间。如果您正在测试所有答案,那么在所有答案中添加一条注释,说明它的性能,对每个人都有帮助
ALTER TABLE tbl_profile
  DROP PRIMARY KEY,
  DROP COLUMN id,
  ADD CONSTRAINT profile_PK
    PRIMARY KEY (user_id),
  ADD CONSTRAINT user_profile_FK 
    FOREIGN KEY (user_id)
    REFERENCES tbl_user (id) ; 
select p.name
from user_profile p
join user u on p.user_id = u.user_id and u.verified = 1;