2012-01-24 25 views
1

好的,所以我很抱歉,如果这个问题太基本了,但我通常只处理编程问题,而不是DBA问题。基本上,我试图加快这个Django应用程序(注意:我没有设计这个...只是坚持保持它),最大的瓶颈似乎是管理员正在生成的这些查询。我们有一个内容类4-5其他子类继承,随时随地主列表中会产生这样的查询管理员拉升:SQL查询优化

SELECT `content_content`.`id`, 
     `content_content`.`issue_id`, 
     `content_content`.`slug`, 
     `content_content`.`section_id`, 
     `content_content`.`priority`, 
     `content_content`.`group_id`, 
     `content_content`.`rotatable`, 
     `content_content`.`pub_status`, 
     `content_content`.`created_on`, 
     `content_content`.`modified_on`, 
     `content_content`.`old_pk`, 
     `content_content`.`content_type_id`, 
     `content_image`.`content_ptr_id`, 
     `content_image`.`caption`, 
     `content_image`.`kicker`, 
     `content_image`.`pic`, 
     `content_image`.`crop_x`, 
     `content_image`.`crop_y`, 
     `content_image`.`crop_side`, 
     `content_issue`.`id`, 
     `content_issue`.`special_issue_name`, 
     `content_issue`.`web_publish_date`, 
     `content_issue`.`issue_date`, 
     `content_issue`.`fm_name`, 
     `content_issue`.`arts_name`, 
     `content_issue`.`comments`, 
     `content_section`.`id`, 
     `content_section`.`name`, 
     `content_section`.`audiodizer_id` 
    FROM `content_image` 
INNER 
    JOIN `content_content` 
    ON `content_image`.`content_ptr_id` = `content_content`.`id` 
INNER 
    JOIN `content_issue` 
    ON `content_content`.`issue_id` = `content_issue`.`id` 
INNER 
    JOIN `content_section` 
    ON `content_content`.`section_id` = `content_section`.`id` 
WHERE NOT (`content_content`.`pub_status` = -1) 
ORDER BY `content_issue`.`issue_date` DESC LIMIT 30 

我跑这一个解释并得到了以下:现在

+----+-------------+-----------------+--------+-------------------------------------------------------------------------------------------------+---------+---------+--------------------------------------+-------+---------------------------------+ 
| id | select_type | table   | type | possible_keys                     | key  | key_len | ref         | rows | Extra       | 
+----+-------------+-----------------+--------+-------------------------------------------------------------------------------------------------+---------+---------+--------------------------------------+-------+---------------------------------+ 
| 1 | SIMPLE  | content_image | ALL | PRIMARY                       | NULL | NULL | NULL         | 40499 | Using temporary; Using filesort | 
| 1 | SIMPLE  | content_content | eq_ref | PRIMARY,issue_id,content_content_issue_id,content_content_section_id,content_content_pub_status | PRIMARY | 4  | content_image.content_ptr_id   |  1 | Using where      | 
| 1 | SIMPLE  | content_section | eq_ref | PRIMARY                       | PRIMARY | 4  | content_content.section_id   |  1 |         | 
| 1 | SIMPLE  | content_issue | eq_ref | PRIMARY                       | PRIMARY | 4  | content_content.issue_id    |  1 |         | 
+----+-------------+-----------------+--------+-------------------------------------------------------------------------------------------------+---------+---------+--------------------------------------+-------+---------------------------------+ 

,从我读过,我需要以某种方式弄清楚如何使查询content_image不可怕;然而,我正在从哪里开始画空白。 SQL并不完全是我最强大的领域,所以任何帮助将不胜感激。

+0

您从'content_image'表中选择** everything **(因为您没有任何可以过滤掉某些行的WHERE) - 所以您有一个表fullscan。你还期望看到什么? – zerkms

回答

2

目前,通过执行计划判断,MySQL是开始content_image,检索所有行,并且仅在其后使用主键上的其他表:content_image具有外键content_content,和content_content具有外键content_issuecontent_section。另外,只有在所有连接完成之后,才可以使用ORDER BY content_issue.issue_date DESC LIMIT 30,因为它无法分辨哪些连接可能会失败,因此,在获得前三十个连接之前真的需要多少个content_issue的记录输出行。

所以,我会尝试以下方法:

  • 变化JOIN content_issueJOIN (SELECT * FROM content_issue ORDER BY issue_date DESC LIMIT 30) content_issue。这将允许MySQL,如果它以content_issue开头,并且运行到其他表,则可以获取content_issue的一个非常小的子集。
    • 注意:正确地说,这改变了查询的语义:这意味着最多只有最后30个content_issue的记录才会被检索到,因此如果其中一些问题没有发布带有图像的内容,那么将检索少于30条记录。我没有足够的关于数据的信息来判断这种语义变化是否会改变你得到的结果。
    • 另请注意:我不建议从查询结尾删除ORDER BY content_issue.issue_date DESC LIMIT 30。我想你想在两个地方。
  • content_issue.issue_date上添加索引来优化上述子查询。
  • content_image.content_ptr_id上添加索引,因此MySQL可以在不进行全表扫描的情况下从content_contentcontent_image工作。
+0

感谢您的帮助和解释!我会给它一个镜头。 – ebensing