草庐IT

大表上的 MySQL 查询优化

coder 2023-10-25 原文

我正在使用 mysql 查询一个表,该表有 1200 万个寄存器,这些寄存器是上述数据的一年。 查询必须选择某种数据(硬币、企业、类型等),然后为该数据的某些字段提供每日平均值,以便我们之后可以绘制图表。 梦想能够实时执行此操作,因此响应时间少于 10 秒,但目前它看起来一点也不亮,因为它需要 4 到 6 分钟。 例如,其中一个 where 查询产生了 150k 个寄存器,每天拆分大约 500 个,然后我们使用 AVG() 和 GroupBy 平均三个字段(不在 where 子句上)。

现在,对于原始数据,查询是

SELECT 
`Valorizacion`.`fecha`, AVG(tir) AS `tir`, AVG(tirBase) AS `tirBase`, AVG(precioPorcentajeValorPar) AS `precioPorcentajeValorPar` 
FROM `Valorizacion` USE INDEX (ix_mercado2)
WHERE
(Valorizacion.fecha >= '2011-07-17' ) AND
(Valorizacion.fecha <= '2012-07-18' ) AND
(Valorizacion.plazoResidual >= 365 ) AND
(Valorizacion.plazoResidual <= 3650000 ) AND
(Valorizacion.idMoneda_cache IN ('UF')) AND
(Valorizacion.idEmisorFusionado_cache IN ('ABN AMRO','WATTS', ...)) AND
(Valorizacion.idTipoRA_cache IN ('BB', 'BE', 'BS', 'BU'))
GROUP BY `Valorizacion`.`fecha` ORDER BY `Valorizacion`.`fecha` asc;

248 rows in set (4 min 28.82 sec)

索引是遍历顺序中的所有where子句字段

(fecha, idTipoRA_cache, idMoneda_cache, idEmisorFusionado_cache, plazoResidual)

选择“where”寄存器,不使用 group by 或 AVG

149670 rows in set (58.77 sec)

然后选择寄存器,分组并只做一个计数(*)而不是平均花费

248 rows in set (35.15 sec)

这可能是因为它不需要去磁盘上搜索数据,而是直接从索引查询中获取数据。

就目前而言,我的想法是告诉我的老板“很抱歉,但它无法完成”,但在这样做之前,我来找你们问问你们是否认为我可以做些什么来改善这一点。我认为我可以通过索引时间将具有最大基数的索引移到前面等来改进搜索,但即使在那之后,为每条记录访问磁盘和执行 AVG 所花费的时间似乎太多了。

有什么想法吗?

-- 编辑,表结构

CREATE TABLE `Valorizacion` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `idInstrumento` int(11) NOT NULL,
  `fecha` date NOT NULL,
  `tir` decimal(10,4) DEFAULT NULL,
  `tirBase` decimal(10,4) DEFAULT NULL,
  `plazoResidual` double NOT NULL,
  `duracionMacaulay` double DEFAULT NULL,
  `duracionModACT365` double DEFAULT NULL,
  `precioPorcentajeValorPar` decimal(20,15) DEFAULT NULL,
  `valorPar` decimal(20,15) DEFAULT NULL,
  `convexidad` decimal(20,15) DEFAULT NULL,
  `volatilidad` decimal(20,15) DEFAULT NULL,
  `montoCLP` double DEFAULT NULL,
  `tirACT365` decimal(10,4) DEFAULT NULL,
  `tipoVal` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
  `idEmisorFusionado_cache` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
  `idMoneda_cache` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
  `idClasificacionRA_cache` int(11) DEFAULT NULL,
  `idTipoRA_cache` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `fechaPrepagable_cache` date DEFAULT NULL,
  `tasaEmision_cache` decimal(10,4) DEFAULT NULL,
  PRIMARY KEY (`id`,`fecha`),
  KEY `ix_FechaNemo` (`fecha`,`idInstrumento`) USING BTREE,
  KEY `ix_mercado_stackover` (`idMoneda_cache`,`idTipoRA_cache`,`idEmisorFusionado_cache`,`plazoResidual`)
) ENGINE=InnoDB AUTO_INCREMENT=12933194 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

最佳答案

无论您尝试做什么,从 12M 记录中选择 150K 条记录并对它们执行聚合函数都不会很快。

您可能主要处理历史数据,因为您的示例查询是针对一年的数据。更好的方法可能是预先计算您的每日平均值并将它们放入单独的表格中。然后您可以查询这些表以获取报告、图表等。您需要决定何时以及如何运行此类计算,这样您就不需要对相同的数据再次运行它们。

当您的要求是对数百万条历史记录进行分析和报告时,您需要考虑数据仓库方法 http://en.wikipedia.org/wiki/Data_warehouse而不是简单的数据库方法。

关于大表上的 MySQL 查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11678513/

有关大表上的 MySQL 查询优化的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  3. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  4. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  5. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  6. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  7. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  8. ruby-on-rails - Ruby - 如何从 ruby​​ 上的 .pfx 文件中提取公钥、rsa 私钥和 CA key - 2

    我有一个.pfx格式的证书,我需要使用ruby​​提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o

  9. 带有 attr_accessor 的类上的 Ruby instance_eval - 2

    我了解instance_eval和class_eval之间的基本区别。我在玩弄时发现的是一些涉及attr_accessor的奇怪东西。这是一个例子:A=Class.newA.class_eval{attr_accessor:x}a=A.newa.x="x"a.x=>"x"#...expectedA.instance_eval{attr_accessor:y}A.y="y"=>NoMethodError:undefinedmethod`y='forA:Classa.y="y"=>"y"#WHATTT?这是怎么回事:instance_eval没有访问我们的A类(对象)然后它实际上将它添加到

  10. ruby-on-rails - rails 上的 ruby : radio buttons for collection select - 2

    我有一个集合选择:此方法的单选按钮是什么?谢谢 最佳答案 Rails3中没有这样的助手。在Rails4中,它是collection_radio_buttons. 关于ruby-on-rails-rails上的ruby:radiobuttonsforcollectionselect,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/18525986/

随机推荐