【发布时间】:2015-01-13 21:46:11
【问题描述】:
我有一个查询将平均值添加到现有平均值中,我已经缩短了示例中插入的行数,但通常我们每天多次执行 5,000 行。
INSERT INTO stats (impcount,
average_position,
state,
dir_id,
viz_id,
date_date,
org_id,
order_id) VALUES
('2', '1', '', '5537', '22189', '2014-11-06', '-1', '15963'),
('2', '2', '', '5624', '22020', '2014-11-06', '-1', '15963'),
('2', '3', '', '5624', '18215', '2014-11-06', '-1', '15963'),
('2', '4', '', '6153', '22071', '2014-11-06', '-1', '15963'),
('1', '9', '', '5624', '21735', '2014-11-06', '-1', '15634')
ON DUPLICATE KEY UPDATE impcount = impcount + VALUES(impcount),
average_position = VALUES(average_position) + ((((average_position * impcount)
+ ( VALUES(impcount) * VALUES(average_position)) ) / (impcount + VALUES(impcount) ))
- average_position);
表结构如下:
CREATE TABLE stats (
record_id bigint(10) NOT NULL AUTO_INCREMENT,
date_year varchar(4) DEFAULT NULL,
date_month char(2) DEFAULT NULL,
date_day char(2) DEFAULT NULL,
impcount int(10) DEFAULT NULL,
date_hour varchar(4) DEFAULT NULL,
dir_id bigint(20) unsigned DEFAULT NULL,
viz_id int(9) NOT NULL DEFAULT '0',
order_id int(3) DEFAULT '0',
date_date date NOT NULL DEFAULT '0000-00-00',
average_position double DEFAULT NULL,
state varchar(200) DEFAULT NULL,
org_id int(10) unsigned DEFAULT NULL,
PRIMARY KEY (record_id),
UNIQUE KEY viz_id (viz_id,order_id,date_date,org_id),
KEY viz_counts (viz_id,date_date,impcount,average_position,order_id),
KEY daily_counts (date_date,impcount,order_id,average_position),
KEY dir_counts (dir_id,date_date,order_id),
KEY org_id (org_id)
) ENGINE=InnoDB AUTO_INCREMENT=33499742809 DEFAULT CHARSET=latin1;
有没有人知道简化这个的方法,我不是特别了解这背后的数学,但希望有人能认出它并知道更好/更简单/更快的方法来完成同样的事情。
impcount 是每行的展示次数,average_position 是每个展示位置的直接平均值。据我了解,这是一个滚动平均值,其中每个重复键更新都保持平均值准确。
【问题讨论】:
-
如果可行,为什么需要更改它?
-
它可以工作,但速度很慢,每天使用此查询不断更新大约 5000 行 - 我们还有其他数学较少的查询以相同的速度更新,没有任何问题。跨度>
-
算术不太可能导致此查询的性能瓶颈。您可以编辑问题并添加表格定义吗?此外,也许在(大概)您想要数字的地方使用字符串常量可能会减慢查询速度。
-
用表格结构更新问题
-
需要更新2个key,这大概就是花时间的地方了。我不明白
VALUES(average_position) +起始位和 `-average_position` 结束位(恕我直言,它们是错误,应该省略,除非我遗漏了什么),但正如 Gordon 所说: 你的时间不太可能花在哪里。其余的只是计算机的简单数学运算:如果 N 次平均 M,X 次平均 Y,则两者的平均值为((N*M) + (X*Y))/(M+Y)。为 MySQL 提供 integers 或 doubles 而不是 strings 如果这是它想要的,那么你可以赢得一些。
标签: mysql math query-optimization