MySql表性能优化

MySql表性能优化,mysql,sql,Mysql,Sql,我有一张结构如下的桌子 CREATE TABLE rel_score ( user_id bigint(20) NOT NULL DEFAULT '0', score_date date NOT NULL, rel_score decimal(4,2) DEFAULT NULL, doc_count int(8) NOT NULL total_doc_count int(8) NOT NULL PRIMARY KEY (user_id,score_date), KEY

我有一张结构如下的桌子

CREATE TABLE rel_score (
  user_id bigint(20) NOT NULL DEFAULT '0',
  score_date date NOT NULL,
  rel_score decimal(4,2) DEFAULT NULL,
  doc_count int(8) NOT NULL
  total_doc_count int(8) NOT NULL
  PRIMARY KEY (user_id,score_date),
  KEY SCORE_DT_IDX (score_date)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 PACK_KEYS=1
该表将存储自2000年1月1日起至日期的每一天应用程序中每个用户的rel_分数值。我估计总记录数将超过7亿。我用6个月的数据(约3000万行)填充了表,查询响应时间约为8分钟。我的问题是

select 
  user_id, max(rel_score) as max_rel_score
from
  rel_score
where score_date between '2012-01-01' and '2012-06-30'
group by user_id
order by max_rel_score desc;
我尝试使用以下技术优化查询

  • 在score\u date列上进行分区
  • 在“分数\日期”列中添加索引
  • 查询响应时间略微提高到略少于8分钟

    如何提高响应时间?桌子的设计合适吗


    此外,我无法将旧数据移动到存档,因为允许用户查询整个数据范围。

    如果您将表划分到评分日期的同一级别,则不会减少查询响应时间


    尝试创建另一个只包含日期年份的属性,将其强制转换为整数,在此属性上对表进行分区(您将得到13个分区),然后重新执行查询以查看。

    您的主索引应该能够很好地覆盖表。如果没有,我建议在
    rel\u分数(用户id、分数日期、rel\u分数)
    上建立索引。对于您的查询,这是一个“覆盖”索引,这意味着该索引包含查询中的所有列,因此引擎永远不必访问数据页(只有索引)

    以下版本也可能会很好地利用此索引(尽管我更喜欢您的查询版本):


    此查询背后的想法是用简单的索引查找替换聚合。MySQL中的聚合是一个缓慢的操作——它在其他数据库中工作得更好,因此不需要这些技巧。

    您可以发布执行计划吗。我认为
    score\u date
    上的索引实际上可能会减慢查询速度,因为它会使优化者进行索引搜索和查找操作,而表扫描会更有效?最后,我不反对MySQL,但是如果您有一个具有150 K用户的应用程序,它已经建立了13年,并且提供了查询所有这些13年的能力,那么,有可能考虑从开源数据库DBMS升级吗?当然,因为聚集索引是在<代码>(UsSeriID,SCOREYDATE)< /C>,一个关于<代码>的索引。(user\u id、score\u date、rel\u score)基本上只是复制表(但省略了2列)。我还认为MySQL仍然会选择聚集索引扫描,即使该索引存在(无论如何它都会选择)
    select u.user_id,
           (select max(rel_score)
            from rel_score r2
            where r2.user_id = r.user_id and 
                  r2.score_date between '2012-01-01' and '2012-06-30'
          ) as rel_score
    from (select distinct user_id
          from rel_score
          where score_date between '2012-01-01' and '2012-06-30'
         ) u
    order by rel_score desc;