提高涉及联合的MYSQL查询的性能

提高涉及联合的MYSQL查询的性能,mysql,sql,go,query-performance,sqlperformance,Mysql,Sql,Go,Query Performance,Sqlperformance,有一个Golang实用程序,它能够减少历史数据表中每天的数据点 记录范围为每天20到400条记录。 总共至少有1亿条记录 该实用程序能够在给定日期之前每天将其缩减到n条记录。(n可以是每天1到300条记录) 我使用的方法如下: 步骤1: 创建与main_TABLE类似的表main_TABLE_tmp 步骤2: ALTER TABLE main_TABLE_tmp添加列timekey INT 步骤3: 此查询的当前响应时间非常慢 部分结果: 总记录:200万 执行时间:180秒 这是一个16Gb的

有一个Golang实用程序,它能够减少历史数据表中每天的数据点

记录范围为每天20到400条记录。 总共至少有1亿条记录

该实用程序能够在给定日期之前每天将其缩减到n条记录。(n可以是每天1到300条记录)

我使用的方法如下:

步骤1:

创建与main_TABLE类似的表main_TABLE_tmp

步骤2:

ALTER TABLE main_TABLE_tmp添加列timekey INT

步骤3:

此查询的当前响应时间非常慢

部分结果: 总记录:200万
执行时间:180秒

这是一个16Gb的RAM CPU 当它部署在低级系统上时,速度非常慢

我已采取步骤解决此问题:

  • 查看了所有表的索引。已尝试删除索引并运行该实用程序。删除索引使实用程序的速度提高了5秒,这也不算多

  • 分阶段执行实用程序:如果总记录超过100万条,则一次运行100万条实用程序

  • 但是在所有这些努力之后,看起来主要的问题在于查询本身

    只是速度不够快。我只需要一种提高查询效率的方法

    感谢您的帮助,
    谢谢大家

    为什么我们要添加
    timekey
    然后删除它?将其添加到空表很快,但在填充后将其从表中删除,这就像是该表的额外副本。如果我们不需要的话,那是不必要的工作

    我们可以对表达式进行
    分组;该表达式不必出现在选择列表中,例如:

    SELECT t.*
      FROM main_table t
     WHERE t.column_name <= '2018-01-01'
     GROUP 
        BY FLOOR(UNIX_TIMESTAMP(t.column_name)/((1440/2)*60))
    

    “这是在16Gb RAM CPU上,当它部署在低级系统上时速度非常慢”这是指MySQL服务器还是运行此实用程序的机器?由于该实用程序是通过插入到…选择来完成这一切的,因此该实用程序本身基本上不应该使用任何资源,它只是在MySQL上等待;您可能希望通过确保
    SELECT
    使用了良好的索引(
    EXPLAIN
    会告诉您),来加快数据库端的速度删除目标上的所有索引,并在插入完成后将其添加回。您还可以尝试转储
    联合
    ,然后只在…SELECT
    中运行两个单独的
    插入。每个查询一个。这些索引在MySQL服务器上使用,因此需要大量内存。Go工具,基于您在这里展示的内容,应该使用很少的内存和CPU。它所做的只是发送一个不返回结果的查询,然后等待它完成。@RaymondNijland是的,我通过禁用它来规避mysql函数依赖性。但是这个查询能够达到它的目的,而且是准确的。但是这个查询可以被修改以使其符合函数依赖性吗???。我没有找到任何其他方法不必在查询中使用主表的列名。我希望这个实用程序是通用的。你的意思是你禁用了sql模式,只禁用了完整的组,我想你喜欢玩俄罗斯轮盘赌,因为这就是你正在做的。我很抱歉让大家感到困惑,列名本身就是“日期”。我现在已经编辑了这个问题!:)将
    t.*
    改为拼写列,然后将
    t.date
    替换为
    FLOOR(…)
    。更好的方法是,通过乘法和
    从_UNIXTIME
    (或任何内容)将
    楼层
    转换回日期时间(或任何内容)。另外,将其他列更改为
    AVG(t.temp)作为temp
    ,等等,将
    MIN(id)作为id
    。Etc,Etc——这避免了
    仅\u FULL\u GROUP\u BY
    问题。@RickJames:是的,我们应该枚举选择列表中的所有表达式。但这似乎是试图通过创建一个新表,只复制要保留的行,然后交换表,从表中删除一整组行;给定
    创建表。。。就像同一个脚本中的
    一样,我可以使用SELECT*并从INSERT中省略列列表。@RickJames:我完全同意用非决定性列(SELECT中的非聚合不在GROUP BY中)来解决问题,只解决\u FULL\u GROUP BY问题。。。我在回答中确实提到了这个问题。至于如何解决这个问题,我可以回答,但这似乎是一个不同于被问到的问题。(为了正确地修复它,我需要主键或非空的唯一键,然后我可以创建SQL。)
    func somefuncname(){
    
      ---- 
      ----
      ----
      q := "CREATE TABLE " + *tablename + "_tmp LIKE " + *tablename + ";"
      rows, err := db.Query(q)
      if err != nil {
      fmt.Println(err)
      }
    //--ALTER ADD timekey
    //--INSERT INTO SELECT *....
    //--ALTER DROP timekey ,DROP table and rename
    
    }
    
    SELECT t.*
      FROM main_table t
     WHERE t.column_name <= '2018-01-01'
     GROUP 
        BY FLOOR(UNIX_TIMESTAMP(t.column_name)/((1440/2)*60))
    
    CREATE TABLE main_table_tmp LIKE main_table
    ;
    
    -- for performance, remove secondary indexes, leave just the cluster index
    ALTER TABLE main_table_tmp 
        DROP INDEX noncluster_index_1
      , DROP INDEX noncluster_index_2
      , ...
    ;
    
    -- for performance, have a suitable index available on main_table 
    -- with `column_name` as the leading column
    INSERT INTO main_table_tmp 
    SELECT h.*
      FROM main_table h
     WHERE h.column_name <= '2018-01-01'
     GROUP 
        BY FLOOR(UNIX_TIMESTAMP(h.column_name)/((1440/2)*60))
    ;
    
    -- for performance, have a suitable index available on main_table
    -- with `date` as the leading column
    INSERT INTO main_table_tmp
    SELECT c.*
      FROM main_table
     WHERE c.date > '????-??-??'
    ;
    
    -- add secondary indexes 
    ALTER TABLE maint_table_tmp
        ADD UNIQUE INDEX noncluster_index_1 (fee,fi,fo)
      , ADD INDEX noncluster_index_2 (fum)
      , ...
    ;