2012-07-26 1 views
3

Я работаю с mysql, запрашивающим таблицу с 12 миллионами регистров, которые являются годом данных. Запрос должен выбрать определенный тип данных (монета, предприятие, тип и т. Д.), А затем предоставить среднесуточное значение для определенных полей этих данных, чтобы потом мы могли графически их отображать. Мечта, чтобы это можно было сделать в режиме реального времени, поэтому время отклика менее 10 секунд, однако на данный момент его не выглядит ярким, поскольку он занимает от 4 до 6 минут. Например, один из запросов содержит 150 тыс. Регистров, разбивается примерно на 500 в день, а затем мы усредняем три поля (которые не входят в предложение where) с использованием AVG() и GroupBy.Оптимизация запросов MySQL в большой таблице

Теперь, к сырым данным, запрос

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) 

Индекс производится по всем где полям Оговорки в порядке

(fecha, idTipoRA_cache, idMoneda_cache, idEmisorFusionado_cache, plazoResidual) 

Выбор «где» регистры, без использования группа или AVG

149670 rows in set (58.77 sec) 

И выбирая регистры, группируя и просто делая счет (*) istead в среднем занимает

248 rows in set (35.15 sec) 

Который, вероятно, его потому, что оно не нужно идти на диск для поиска данных, но его получают непосредственно из индекса запросов.

Так как это касается идеи сказать моему боссу «Мне жаль, но это не может быть сделано», но прежде чем это сделать, я прихожу к вам, ребята, спрашивая, думаете ли вы, что я могу что-то сделать, чтобы улучшить это , Я думаю, что я мог бы улучшить поиск по индексу, перемещая индекс с наибольшей мощностью на фронт и т. Д., Но даже после этого время, которое требуется для доступа к диску для каждой записи, и AVG кажется слишком большим.

Любые идеи?

- EDIT, структура таблицы

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 
+0

Если добавление индекса является опцией (он будет блокировать таблицу на некоторое время), попробуйте добавить это: idMoneda_cache, idTipoRA_cache, idEmisorFusionado_cache, plazoResidual' (не уверен, что 'plazoResidual' или' fecha' должно быть последним). И затем запустите его (или «EXPLAIN') без« USE INDEX ». Причина в том, что MySQL будет использовать индекс только в поле, для которого существует условие диапазона (в вашем случае вы используете только столбец 'fecha' из вашего индекса). – Vatev

+0

Это имеет большой смысл, теперь до 1 минуты 2 секунды. Строки: 193763. Дополнительно: использование где; Использование временных; Использование filesort. Однако все еще слишком медленно, чтобы поместить его на веб-страницу = | – Jimmy

+1

все еще не очень полезен ... можете ли вы опубликовать 'SHOW CREATE TABLE ...' (возможно, без каких-либо несоответствующих столбцов) и полный вывод 'EXPLAIN' – Vatev

ответ

1

Выбор 150K записей из 12M записей и выполнения агрегатных функций на них не будет быстро, независимо от того, что вы пытаетесь сделать.

Возможно, вы имеете дело с прежде всего историческими данными, так как ваш примерный запрос рассчитан на год данных. Лучший подход может заключаться в том, чтобы предварительно вычислить средние дневные средние значения и поместить их в отдельные таблицы. Затем вы можете запросить эти таблицы для отчетов, графиков и т. Д. Вам нужно будет решить, когда и как запускать такие вычисления, чтобы вам не нужно повторно запускать их снова на одни и те же данные.

Если вам необходимо выполнить анализ и отчетность по миллионам исторических записей, вам необходимо рассмотреть подход к хранилищу данных http://en.wikipedia.org/wiki/Data_warehouse, а не простой подход к базе данных.

+0

Вы абсолютно правы, спасибо :) – Jimmy

 Смежные вопросы

  • Нет связанных вопросов^_^