我有MySQL
个查询,其中有JOIN
个12个表。当我explain
查询时,它显示一个表的394699行和另一个表的185368行。所有其他表有1-3行。我从查询ID获得的总结果仅为472行。但就此而言,需要超过1分钟。
有没有办法检查分析了多少行来产生这样的结果?所以,我可以找到哪个表花费的时间越长。
我在下面给出了查询结构。由于表格结构太高,我无法在此处提供。
SELECT h.nid,h.attached_nid,h.created, s.field_species_value as species, g.field_gender_value as gender, u.field_unique_id_value as unqid, n.title, dob.field_adult_healthy_weight_value as birth_date, dcolor.field_dog_primary_color_value as dogcolor, ccolor.field_primary_color_value as catcolor, sdcolor.field_dog_secondary_color_value as sdogcolor, sccolor.field_secondary_color_value as scatcolor, dpattern.field_dog_pattern_value as dogpattern, cpattern.field_cat_pattern_value as catpattern
FROM table1 h
JOIN table2 n ON n.nid = h.nid
JOIN table3 s ON n.nid = s.entity_id
JOIN table4 u ON n.nid = u.entity_id
LEFT JOIN table5 g ON n.nid = g.entity_id
LEFT JOIN table6 dob ON n.nid = dob.entity_id
LEFT JOIN table7 AS dcolor ON n.nid = dcolor.entity_id
LEFT JOIN table8 AS ccolor ON n.nid = ccolor.entity_id
LEFT JOIN table9 AS sdcolor ON n.nid = sdcolor.entity_id
LEFT JOIN table10 AS sccolor ON n.nid = sccolor.entity_id
LEFT JOIN table11 AS dpattern ON n.nid = dpattern.entity_id
LEFT JOIN table12 AS cpattern ON n.nid = cpattern.entity_id
WHERE h.title = '4208'
AND ((h.created BETWEEN 1483257600 AND 1485935999))
AND h.uid!=1
AND h.uid IN(
SELECT etid
FROM `table`
WHERE gid=464
AND entity_type='user')
AND h.attached_nid>0
ORDER BY CAST(h.created as UNSIGNED) DESC;
以下是我获得的EXPLAIN结果
+------+--------------+---------------+--------+----------------------+---------------------+---------+----------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------+---------------+--------+----------------------+---------------------+---------+----------------------+--------+----------------------------------------------+
| 1 | PRIMARY | s | index | entity_id | field_species_value | 772 | NULL | 394699 | Using index; Using temporary; Using filesort |
| 1 | PRIMARY | u | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | n | eq_ref | PRIMARY | PRIMARY | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | g | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | dob | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | dcolor | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | ccolor | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | sdcolor | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | sccolor | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | dpattern | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | cpattern | ref | entity_id | entity_id | 4 | pantheon.s.entity_id | 1 | |
| 1 | PRIMARY | h | ref | attached_nid,nid,uid | nid | 5 | pantheon.s.entity_id | 3 | Using index condition; Using where |
| 1 | PRIMARY | <subquery2> | eq_ref | distinct_key | distinct_key | 4 | func | 1 | Using where |
| 2 | MATERIALIZED | og_membership | ref | entity,gid | gid | 4 | const | 185368 | Using where |
+------+--------------+---------------+--------+----------------------+---------------------+---------+----------------------+--------+----------------------------------------------+
答案 0 :(得分:0)
您可以使用效果架构找到ROWS_EXAMINED
。
以下是性能架构快速入门指南的链接。 https://dev.mysql.com/doc/refman/5.5/en/performance-schema-quick-start.html
这是我在PHP应用程序中运行的查询,以找出我需要优化的查询。你应该能够很容易地适应它。
查询查找在此查询之前运行的查询的统计信息。所以在我的应用程序中,我在运行的每个查询之后运行查询,存储结果,然后在PHP脚本的末尾,我输出我在请求期间运行的每个查询的统计信息。
SELECT `EVENT_ID`, TRUNCATE(`TIMER_WAIT`/1000000000000,6) as Duration,
`SQL_TEXT`, `DIGEST_TEXT`, `NO_INDEX_USED`, `NO_GOOD_INDEX_USED`, `ROWS_AFFECTED`, `ROWS_SENT`, `ROWS_EXAMINED`
FROM `performance_schema`.`events_statements_history`
WHERE
`CURRENT_SCHEMA` = '{$database}' AND `EVENT_NAME` LIKE 'statement/sql/%'
AND `THREAD_ID` = (SELECT `THREAD_ID` FROM `performance_schema`.`threads` WHERE `performance_schema`.`threads`.`PROCESSLIST_ID` = CONNECTION_ID())
ORDER BY `EVENT_ID` DESC LIMIT 1;
答案 1 :(得分:0)
要减少从og_membership
访问的行数,请尝试添加包含gid
,entity_type
和etid
字段的索引。包括gid
和entity_type
应该使查找更具效果,包括etid
将使索引成为覆盖索引。
添加索引后,再次运行EXPLAIN
以查看结果。根据新的解释计划,保留索引,删除索引和/或添加其他索引。继续这样做,直到你得到满意的结果。
当然,您可以尝试消除Using temporary
或Using filesort
的任何提及。 Using temporary
表示正在使用临时表来进行此查询,可能是因为间歇性的大小。 Using filesort
意味着排序并不满足于索引,而是通过检查匹配的行来完成。
有关EXPLAIN
的详细说明,请访问https://dev.mysql.com/doc/refman/5.7/en/explain-output.html。
答案 2 :(得分:0)
键值(EAV)架构很糟糕。
索引:
table1: INDEX(title, created)
table1: INDEX(uid, title, created)
table: INDEX(gid, entity_type, etid)
table* -- Is `entity_id` already an index? Can it be the PRIMARY KEY?
nid
需要NULL
而不是NOT NULL
吗?
如果那些人做得不够,请尝试:
然后将IN ( SELECT ... )
变成JOIN ( SELECT ... ) USING(hid)
如果您仍需要帮助,请提供SHOW CREATE TABLE
和EXPLAIN SELECT ...