【问题标题】:mysql slow query for little data setmysql对小数据集的慢查询
【发布时间】:2016-10-09 07:02:47
【问题描述】:

描述:

profit大约有20列,没有text这样的大列,并且有两个索引:

  1. 索引idx_uid 在列uid
  2. 索引uid_acc_fId_date 在列uid,acc,fid and date

慢查询sql为:

select * from profit where (((uid='1111') and (flag=32)) and (fId='2222')) and (date='20161008') limit 1;

解释输出为:

id:1
select_type:SIMPLE
table:profit
type:ref
possible_keys:uid_acc_fId_date
key:uid_acc_fId_date
key_len:4
ref:const
rows:267
Extra:Using where

执行sql_no_cache的sql大约需要2s,第二次使用sql_no_cache执行同样的sql大约需要0.1s。

环境:

  1. mysql 5.5.49-37.9,innodb,percona
  2. SATA 硬盘
  3. 表利润大约有一百万行
  4. Centos 2.6 内核
  5. uid=1111 的行数仅为 270

PS:

Mysql每天半夜都会备份,而innodb_old_blocks_time是0,我觉得备份会把所有热点数据都冲出缓冲池。但即便如此,上面的查询还是花费了太多时间。所以,是磁盘问题吗?

【问题讨论】:

  • 如果删除flag=32,会找到多少行?因为对于flag,您没有指定索引,所以mysql需要获取所有具有uid='1111' and fId='2222' and date='20161008'的行,然后检查flag是否为32
  • 感谢您的宝贵时间。而uid=1111 的所有数据行只有 270 行
  • 请提供SHOW CREATE TABLE
  • 系统迁移到AWS后解决。。。

标签: mysql innodb mysql-slow-query-log


【解决方案1】:

扩展上面的注释,将索引 uid_acc_fId_date 更改为 (uid,fid,date,acc) 并将查询更改为:

SELECT columns
     , I
     , actually
     , want
  FROM profit 
 WHERE uid = 1111 
   AND fId = 2222
   AND date='20161008'
   AND flag = 32
 ORDER 
    BY uid
 LIMIT 1;

【讨论】:

    【解决方案2】:

    尝试选择查询时始终使用列名。像SELECT name, class_name from table_name;

    【讨论】:

    • 谢谢!是个好建议,也许我会试一试,但是我们的项目真的很难做到,因为要修改的太多了,而且修改之前的代码是有风险的。其实我觉得不是这个问题的关键
    • 好建议,但可能与这里的呆滞无关。
    【解决方案3】:

    尝试删除where条件中的所有括号。不必要的括号导致mysql无法正确使用索引。

    select * 
    from profit 
    where 
         uid='1111' 
         and flag=32 
         and fId='2222' 
         and date='20161008' 
    limit 1;
    

    【讨论】:

    • 感谢您的宝贵时间!括号是由框架添加的。正如你所说,我删除了所有括号,解释输出是一样的。
    • 如你所说,uid=1111 的所有数据行只有 270 行。如果使用uid_acc_fId_date的索引,是不可能使用2s的。
    • MySQL 解析器擅长忽略多余的括号。
    猜你喜欢
    • 2016-07-25
    • 1970-01-01
    • 2012-05-31
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-22
    相关资源
    最近更新 更多