索引并加速“派生”;查询
我最近注意到我的一个查询运行速度非常慢,每个查询几乎需要 1 秒。
查询看起来像这样
SELECT eventdate.id, eventdate.eid, eventdate.date, eventdate.time, eventdate.title, eventdate.address, eventdate.rank, eventdate.city, eventdate.state, eventdate.name, source.link, type, eventdate.img FROM source RIGHT OUTER JOIN ( SELECT event.id, event.date, users.name, users.rank, users.eid, event.address, event.city, event.state, event.lat, event.`long`, GROUP_CONCAT(types.type SEPARATOR ' | ') AS type FROM event FORCE INDEX (latlong_idx) JOIN users ON event.uid = users.id JOIN types ON users.tid=types.id WHERE `long` BETWEEN -74.36829174058 AND -73.64365405942 AND lat BETWEEN 40.35195025942 AND 41.07658794058 AND event.date >= '2009-10-15' GROUP BY event.id, event.date ORDER BY event.date, users.rank DESC LIMIT 0, 20 )eventdate ON eventdate.uid = source.uid AND eventdate.date = source.date;
,解释是
+----+-------------+------------+--------+---------------+-------------+---------+------------------------------+-------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+-------------+---------+------------------------------+-------+---------------------------------+ | 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 20 | | | 1 | PRIMARY | source | ref | iddate_idx | iddate_idx | 7 | eventdate.id,eventdate.date | 156 | | | 2 | DERIVED | event | ALL | latlong_idx | NULL | NULL | NULL | 19500 | Using temporary; Using filesort | | 2 | DERIVED | types | ref | eid_idx | eid_idx | 4 | active.event.id | 10674 | Using index | | 2 | DERIVED | users | eq_ref | id_idx | id_idx | 4 | active.types.id | 1 | Using where | +----+-------------+------------+--------+---------------+-------------+---------+------------------------------+-------+---------------------------------+
我尝试在经纬度上使用“强制索引”,但这似乎根本没有加快速度。
是派生表导致响应缓慢吗?如果是这样,有没有办法提高它的性能?
- - - - 编辑 - - - - - - - 我尝试改进格式以使其更具可读性,并且
我运行相同的查询,仅更改 'WHERE 语句,因为
WHERE users.id = ( SELECT users.id FROM users WHERE uidname = 'frankt1' ORDER BY users.approved DESC , users.rank DESC LIMIT 1 ) AND date & gt ; = '2009-10-15' GROUP BY date ORDER BY date)
该查询在 0.006 秒内运行,
解释如下
+----+-------------+------------+-------+---------------+---------------+---------+------------------------------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+-------+---------------+---------------+---------+------------------------------+------+----------------+ | 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 42 | | | 1 | PRIMARY | source | ref | iddate_idx | iddate_idx | 7 | eventdate.id,eventdate.date | 156 | | | 2 | DERIVED | users | const | id_idx | id_idx | 4 | | 1 | | | 2 | DERIVED | event | range | eiddate_idx | eiddate_idx | 7 | NULL | 24 | Using where | | 2 | DERIVED | types | ref | eid_idx | eid_idx | 4 | active.event.bid | 3 | Using index | | 3 | SUBQUERY | users | ALL | idname_idx | idname_idx | 767 | | 5 | Using filesort | +----+-------------+------------+-------+---------------+---------------+---------+------------------------------+------+----------------+
I've recently noticed that a query I have is running quite slowly, at almost 1 second per query.
The query looks like this
SELECT eventdate.id, eventdate.eid, eventdate.date, eventdate.time, eventdate.title, eventdate.address, eventdate.rank, eventdate.city, eventdate.state, eventdate.name, source.link, type, eventdate.img FROM source RIGHT OUTER JOIN ( SELECT event.id, event.date, users.name, users.rank, users.eid, event.address, event.city, event.state, event.lat, event.`long`, GROUP_CONCAT(types.type SEPARATOR ' | ') AS type FROM event FORCE INDEX (latlong_idx) JOIN users ON event.uid = users.id JOIN types ON users.tid=types.id WHERE `long` BETWEEN -74.36829174058 AND -73.64365405942 AND lat BETWEEN 40.35195025942 AND 41.07658794058 AND event.date >= '2009-10-15' GROUP BY event.id, event.date ORDER BY event.date, users.rank DESC LIMIT 0, 20 )eventdate ON eventdate.uid = source.uid AND eventdate.date = source.date;
and the explain is
+----+-------------+------------+--------+---------------+-------------+---------+------------------------------+-------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+-------------+---------+------------------------------+-------+---------------------------------+ | 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 20 | | | 1 | PRIMARY | source | ref | iddate_idx | iddate_idx | 7 | eventdate.id,eventdate.date | 156 | | | 2 | DERIVED | event | ALL | latlong_idx | NULL | NULL | NULL | 19500 | Using temporary; Using filesort | | 2 | DERIVED | types | ref | eid_idx | eid_idx | 4 | active.event.id | 10674 | Using index | | 2 | DERIVED | users | eq_ref | id_idx | id_idx | 4 | active.types.id | 1 | Using where | +----+-------------+------------+--------+---------------+-------------+---------+------------------------------+-------+---------------------------------+
I've tried using 'force index' on latlong, but that doesn't seem to speed things up at all.
Is it the derived table that is causing the slow responses? If so, is there a way to improve the performance of this?
--------EDIT-------------
I've attempted to improve the formatting to make it more readable, as well
I run the same query changing only the 'WHERE statement as
WHERE users.id = ( SELECT users.id FROM users WHERE uidname = 'frankt1' ORDER BY users.approved DESC , users.rank DESC LIMIT 1 ) AND date & gt ; = '2009-10-15' GROUP BY date ORDER BY date)
That query runs in 0.006 seconds
the explain looks like
+----+-------------+------------+-------+---------------+---------------+---------+------------------------------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+-------+---------------+---------------+---------+------------------------------+------+----------------+ | 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 42 | | | 1 | PRIMARY | source | ref | iddate_idx | iddate_idx | 7 | eventdate.id,eventdate.date | 156 | | | 2 | DERIVED | users | const | id_idx | id_idx | 4 | | 1 | | | 2 | DERIVED | event | range | eiddate_idx | eiddate_idx | 7 | NULL | 24 | Using where | | 2 | DERIVED | types | ref | eid_idx | eid_idx | 4 | active.event.bid | 3 | Using index | | 3 | SUBQUERY | users | ALL | idname_idx | idname_idx | 767 | | 5 | Using filesort | +----+-------------+------------+-------+---------------+---------------+---------+------------------------------+------+----------------+
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
清理庞大 SQL 语句的唯一方法是回到绘图板并仔细研究数据库设计和需求。一旦您开始连接 6 个表并使用内部选择,您就应该期待令人难以置信的执行时间。
首先,确保所有 id 字段都已建立索引,但最好确保您的设计有效。我不知道从哪里开始查看你的 SQL - 即使我为你重新格式化了它。
请注意,“使用索引”意味着您在创建或更改正在使用的表时需要发出正确的指令。例如,请参见 MySql 5.0 创建索引
The only way to clean up that mammoth SQL statement is to go back to the drawing board and carefully work though your database design and requirements. As soon as you start joining 6 tables and using an inner select you should expect incredible execution times.
As a start, ensure that all your id fields are indexed, but better to ensure that your design is valid. I don't know where to START looking at your SQL - even after I reformatted it for you.
Note that 'using indexes' means you need to issue the correct instructions when you CREATE or ALTER the tables you are using. See for instance MySql 5.0 create indexes