【发布时间】:2014-08-17 22:04:50
【问题描述】:
此查询在 VPS 上运行 12 秒以上。它连接了 3 个表。只有第一个“topics”大约有 70k 行,其他大约 20 行,“post_cc”大约 1500 行。
SELECT topics.*, employee.username, accounts.ac_name, accounts.ac_mail
FROM topics
INNER JOIN employee ON employee.id_user = topics.id_owner
INNER JOIN accounts ON accounts.id_account = topics.id_account
WHERE topics.status IN ('1','3') AND ( topics.id_owner IN (12, 5) OR topics.id_post IN
(SELECT DISTINCT(id_post) FROM post_cc WHERE id_employee IN (12, 5) ) )
ORDER BY topics.creationdate DESC LIMIT 0,25
我已经尝试(没有任何改进)删除子查询和第一个“员工”加入。如果我删除“accounts”连接,查询将在 0.1 秒内运行,但在分页期间需要所有表数据进行排序。
解释:
+----+--------------------+------------+-----------------+-----------------------+---------+---------+-----------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+-----------------+-----------------------+---------+---------+-----------------+-------+----------------------------------------------+
| 1 | PRIMARY | topics | ALL | id_owner,id_account | NULL | NULL | NULL | 75069 | Using where; Using temporary; Using filesort |
| 1 | PRIMARY | accounts | ALL | PRIMARY | NULL | NULL | NULL | 5 | Using where; Using join buffer |
| 1 | PRIMARY | employee | eq_ref | PRIMARY | PRIMARY | 3 | topics.st_owner | 1 | Using where |
| 2 | DEPENDENT SUBQUERY | post_cc | unique_subquery | PRIMARY | PRIMARY | 8 | func,const | 1 | Using index; Using where |
+----+--------------------+------------+-----------------+-----------------------+---------+---------+-----------------+-------+----------------------------------------------+
我已经添加了建议的键作为索引,它缩短了 2 秒的时间,但它仍然太慢了。
短表:
topics
+--------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+---------------------+------+-----+---------+----------------+
| id_post | int(10) unsigned | NO | PRI | NULL | auto_increment |
| id_account | int(10) unsigned | YES | MUL | 0 | |
| mail | varchar(256) | YES | MUL | NULL | |
| from_name | varchar(512) | YES | | NULL | |
| title | varchar(512) | YES | | NULL | |
| content | text | YES | | NULL | |
| id_owner | int(10) unsigned | YES | MUL | NULL | |
| creationdate | datetime | YES | | NULL | |
+--------------------+---------------------+------+-----+---------+----------------+
employee
+---------------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-----------------------+------+-----+---------+----------------+
| id_employee | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| id_user | mediumint(8) unsigned | NO | | NULL | |
| id_owner | tinyint(1) | YES | | 0 | |
| active | tinyint(1) | YES | | 1 | |
| username | varchar(64) | YES | | NULL | |
| email | varchar(128) | YES | | NULL | |
+---------------------+-----------------------+------+-----+---------+----------------+
accounts
+----------------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+---------------------+------+-----+---------+----------------+
| id_account | int(10) unsigned | NO | PRI | NULL | auto_increment |
| ac_mail | int(10) unsigned | YES | UNI | NULL | |
| ac_name | varchar(512) | YES | | NULL | |
| last_sync_time | datetime | YES | | NULL | |
+----------------------------+---------------------+------+-----+---------+----------------+
post_cc
+------------------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+---------------------+------+-----+---------+-------+
| id_post | int(10) unsigned | NO | PRI | NULL | |
| id_employee | int(10) unsigned | NO | PRI | NULL | |
| notifications | tinyint(3) unsigned | YES | | 1 | |
+------------------------+---------------------+------+-----+---------+-------+
【问题讨论】:
-
+1 表示写得好、问题详细和简短的表格。
-
如果你把它分成两个查询,每个查询都没有
OR,只是为了看看它是否有帮助?我最好的猜测是,在这种情况下,OR是造成问题的原因。 -
在同一个key中添加status、id_owner和id_post的索引。
-
添加了索引,但没有帮助。用左连接替换内部连接似乎正在工作:) 如果我尝试按不在“发件人”表中的列排序,问题仍然存在。知道如何解决吗?我什至已经替换了帐户表的 from/join 并且工作速度非常快,但如果我对员工表执行相同操作,则不会。
标签: php mysql query-optimization