【问题标题】:How to optimize slow Mysql SELECT queries?如何优化缓慢的 Mysql SELECT 查询?
【发布时间】:2015-07-30 22:25:12
【问题描述】:

这是我的查询:

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]

【问题讨论】:

  • 表定义,说明方案
  • 这个查询应该返回多少行?使您的查询变慢的是order by,而不是真正的where 条件
  • 它从50万条记录中返回所有满足条件的记录
  • 一般有多少条记录满足条件?
  • 如果您获取 500000 条记录,那么大约 10000 条记录 - 对于条件 col1= 'val' 的 10000 条记录 7000 条条件的记录 col7='Y' 的 7000 条记录 1000 条条件的记录 col16=' 6000 条记录中的 209 条记录 cpndition col16='201' 的 2000 条记录,因此最终输出大约为 3000 条记录

标签: java mysql sql performance


【解决方案1】:

你确定你的 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

编辑2: OP 编辑​​问题后,列名错误(col2 将是 col7col3 将是 col16

【讨论】:

  • where col1= 'val' and col2='Y' and (col3='203' OR col3='201') 这会有什么不同吗?
  • 当然,它返回一个完全不同的结果。 需要知道你真正想要什么。
  • 查询给出了所需的输出,但我面临的唯一问题是它的输出响应缓慢。
  • @vineeth.soman:所以所有当前的答案都没有解决这个问题,因为他们试图优化错误的查询 :-) 你能提供一些信息,你的查询返回了多少行和col3 的每个值的平均行数(= 选择性)
  • 如果您获取 500000 条记录,那么大约 10000 条记录 - 对于条件 col1= 'val' 的 10000 条记录 7000 条条件的记录 col7='Y' 的 7000 条记录 1000 条条件的记录 col16=' 6000 条记录中的 209 条记录 cpndition col16='201' 的 2000 条记录,因此最终输出大约为 3000 条记录
【解决方案2】:

您的查询 -

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

【讨论】:

  • 这将不会返回与原始查询相同的结果,AND 优先于 OR
  • @dnoeth:你有没有发现这个union all 只是这个答案中第一个查询的拆分?
  • 在原始查询WHERE col1= 'val' AND col2='Y' AND col3='203' OR col3='201' 中我认为这是不正确的,因为没有and ( cond1 or con2) 会导致一些意想不到的结果。
  • @Ravinder Reddy:是的,它基于第一个答案,但第一个答案不会返回与 OP 查询相同的结果集。
  • @dnoeth:OP 可能在不知不觉中使用了这种查询格式。他已经同意建议的查询给出了desired result
【解决方案3】:

我不知道是什么让这个查询变慢了,无论是 order by 还是 conditions..

如果它们是通常的名称、电话号码、电子邮件之类的东西(而不是文档),那么半百万条记录应该可以放入内存中。因此,如果它 - 非常 - 慢,则说明问题非常严重。

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

索引哪些列?您需要按最有效过滤的列进行索引。例如,如果 col2 是对“是”或“否”问题的答案,则按此索引将无济于事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多