3

上記のデータの年である1200万のレジスタを持つテーブルをクエリするmysqlを使用しています。クエリは、特定の種類のデータ (コイン、エンタープライズ、タイプなど) を選択し、そのデータの特定のフィールドの毎日の平均を提供する必要があるため、後でグラフ化できます。夢はこれをリアルタイムでできるようにすることで、応答時間は 10 秒未満ですが、現時点では 4 ~ 6 分かかるため、まったく明るくはありません。たとえば、where クエリの 1 つは 150k のレジスタを生成し、1 日あたり約 500 を分割し、AVG() と GroupBy を使用して 3 つのフィールド (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)

group by または AVG を使用せずに「where」レジスタを選択する

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
4

1 に答える 1

1

12M レコードから 150K レコードを選択し、それらに対して集計関数を実行することは、何をしようとしても高速ではありません。

サンプル クエリは 1 年間のデータを対象としているため、主に過去のデータを扱っている可能性があります。より良いアプローチは、毎日の平均を事前に計算し、それらを別々の表に入れることです. 次に、レポート、グラフなどのためにこれらのテーブルをクエリできます。同じデータに対して再実行する必要がないように、そのような計算をいつ、どのように実行するかを決定する必要があります。

何百万もの履歴レコードの分析とレポート作成が必要な場合は、単純なデータベース アプローチではなく、データ ウェアハウス アプローチhttp://en.wikipedia.org/wiki/Data_warehouseを検討する必要があります。

于 2012-07-26T22:12:41.057 に答える