提高涉及联合的MYSQL查询的性能
有一个Golang实用程序,它能够减少历史数据表中每天的数据点 记录范围为每天20到400条记录。 总共至少有1亿条记录 该实用程序能够在给定日期之前每天将其缩减到n条记录。(n可以是每天1到300条记录) 我使用的方法如下: 步骤1: 创建与main_TABLE类似的表main_TABLE_tmp 步骤2: ALTER TABLE main_TABLE_tmp添加列timekey INT 步骤3: 此查询的当前响应时间非常慢 部分结果: 总记录:200万提高涉及联合的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的
执行时间:180秒 这是一个16Gb的RAM CPU 当它部署在低级系统上时,速度非常慢 我已采取步骤解决此问题:
谢谢大家 为什么我们要添加
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)
, ...
;