如何优化慢速Mysql SELECT查询?

时间:2015-05-19 07:52:22

标签: java mysql sql performance

这是我的问题:

SELECT col1, col2, col3, col4, col5, col6,col7, col8,..,col18
FROM table1
WHERE col1= 'val' and col7='Y' and col16='203' OR col16='201' order by col4 desc

我不知道是什么让这个查询变慢, 是order by还是where子句......

也准确地添加了索引,但它仍然很慢。

我正在使用JSP + STRUTS + EJB2.0 + MYSQL。 table1有超过50万条记录。 如何优化查询或提高执行速度的其他可能性有哪些?

表格结构

col1                varchar(20) NO  PRI 
col2                varchar(50) NO  PRI 
col3                varchar(50) YES     [NULL]
col4                varchar(20) YES     [NULL]
col5                varchar(6)  YES     [NULL]
col6                varchar(20) YES     [NULL]
col7                varchar(1)  YES     [NULL]
col8               mediumtext   YES     [NULL]
col9              mediumtext    YES     [NULL]
col10             mediumtext    YES     [NULL]
col11              mediumtext   YES     [NULL]
col12              mediumtext   YES     [NULL]
col13               mediumtext  YES     [NULL]
col14             mediumtext    YES     [NULL]
col15               mediumtext  YES     [NULL]
col16               varchar(20) YES     [NULL]
col17            varchar(50)    YES     [NULL]
col18             varchar(5)    YES     [NULL]
col19              varchar(5)   YES     [NULL]
col20               varchar(5)  YES     [NULL]
col21                  text YES     [NULL]
col 22                  text    YES     [NULL]
col23              text YES     [NULL]
col24              varchar(5)   YES     [NULL]
col25              int(11)  YES     [NULL]

3 个答案:

答案 0 :(得分:0)

  

我不知道是什么让这个查询变慢,无论是顺序还是条件......

如果他们是通常的名字,电话号码,电子邮件类型的东西(而不是文件),那么50万条记录应该适合记忆。因此,如果它非常慢,那就是非常错误。

  

正确添加索引,仍然很慢。

哪些列被编入索引?您需要按最有效过滤的列进行索引。例如,如果col2是肯定或否定问题的答案,那么它将无助于索引。

答案 1 :(得分:0)

您的查询 -

SELECT col1, col2, col3, col4, col5, col6,col7, col8,..,col18  
FROM table1 
where 
col1= 'val' 
and col2='Y' 
and (col3='203' OR col3='201')
order by col4 desc

首先需要覆盖索引

alter table table1 add index search_idx(col1,col2,col3) ;

现在要解决order by子句,您还需要将其编入索引

alter table table1 add index col4_idx(col4) ;

现在请注意,or条件具有杀手和性能,最好将其转换为union all

SELECT col1, col2, col3, col4, col5, col6,col7, col8,..,col18  
FROM table1 
where 
col1= 'val' 
and col2='Y' 
and col3='203'
union all
SELECT col1, col2, col3, col4, col5, col6,col7, col8,..,col18  
FROM table1 
where 
col1= 'val' 
and col2='Y' 
and col3='201'
order by col4 desc

您可以使用explain select进行上述查询来分析查询运行状况。

确保在应用索引之前备份表。

https://dev.mysql.com/doc/refman/5.0/en/select-optimization.html

https://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

答案 2 :(得分:0)

你确定你的WHERE条件是否正确?

AND优先于OR,所以

where col1= 'val' and col2='Y' and col3='203' OR col3='201'

相同
where (col1= 'val' and col2='Y' and col3='203') OR (col3='201')

但你可能想要

where col1= 'val' and col2='Y' and (col3='203' OR col3='201')

修改 基于你的评论,我的假设是错误的,你实际上想要原始结果(然后我建议添加括号以使其清楚)。在这种情况下唯一可能的索引是col3(如果它有足够的选择性)。

我不知道mysql的优化器是否足够聪明,可以使用相同的索引两次访问一个表,如果不是,你需要UNION ALL两个查询:

SELECT col1, col2, col3, col4, col5, col6,col7, col8,..,col18
FROM table1
WHERE col1= 'val' AND col2='Y' AND col3='203'

UNION ALL

SELECT col1, col2, col3, col4, col5, col6,col7, col8,..,col18
FROM table1
WHERE col3='201'
ORDER BY col4 DESC

EDIT2: 在OP编辑问题后,列名称错误(col2将为col7col3将为col16