Подтвердить что ты не робот

Как оптимизировать ORDER BY для вычисленного столбца таблицы MASSIVE MySQL

У меня очень большая (80 + миллионная строка) де-нормированная таблица MySQL. Упрощенная схема выглядит следующим образом:

+-----------+-------------+--------------+--------------+
|    ID     |   PARAM1    |   PARAM2     |   PARAM3     |
+-----------+-------------+--------------+--------------+
|    1      |   .04       |    .87       |    .78       |
+-----------+-------------+--------------+--------------+
|    2      |   .12       |    .02       |    .76       |
+-----------+-------------+--------------+--------------+
|    3      |   .24       |    .92       |    .23       |
+-----------+-------------+--------------+--------------+
|    4      |   .65       |    .12       |    .01       |
+-----------+-------------+--------------+--------------+
|    5      |   .98       |    .45       |    .65       |
+-----------+-------------+--------------+--------------+

Я пытаюсь выяснить, есть ли способ оптимизировать запрос, в котором я применяю вес к каждому столбцу PARAM (где вес находится между 0 и 1), а затем усредняет их для вычисления вычисленного значения SCORE. Затем я хочу ЗАКАЗАТЬ, что вычисленный столбец SCORE.

Например, если предположить, что взвешивание для PARAM1 равно .5, взвешивание для PARAM2 равно .23, а взвешивание для PARAM3 - 0,76, вы получите нечто похожее на:

SELECT ID, ((PARAM1 * .5) + (PARAM2 * .23) + (PARAM3 * .76)) / 3 AS SCORE 

ORDER BY SCORE DESC LIMIT 10

При некотором правильном индексировании это быстро для базовых запросов, но я не могу найти хороший способ ускорить вышеуказанный запрос на такой большой таблице.

Подробности:

  • Каждое значение PARAM находится между 0 и 1
  • Каждый вес, применяемый к PARAMS, составляет от 0 до 1 с

- EDIT -

Далее следует упрощенная версия проблемы.

Это выполняется в течение разумного промежутка времени:

SELECT value1, value2 
FROM sometable 
WHERE id = 1 
ORDER BY value2

Это не выполняется в течение разумного промежутка времени:

 SELECT value1, (value2 * an_arbitrary_float) as value3 
 FROM sometable 
 WHERE id = 1 
 ORDER BY value3

Используя приведенный выше пример, есть ли какое-либо решение, которое позволяет мне выполнить ORDER BY с вычисленным значением вычисления3 раньше времени?

4b9b3361

Ответ 1

Я нашел 2 (вид очевидных) вещей, которые помогли ускорить этот запрос до удовлетворительного уровня:

  • Свести к минимуму количество строк, которые нужно сортировать. Используя индекс в поле "id" и подзаголовок, чтобы сначала обрезать количество записей, сортировка файла в вычисленном столбце не так уж плоха. Т.е.:

    SELECT t.value1, (t.value2 * an_arbitrary_float) as SCORE
    FROM (SELECT * FROM sometable WHERE id = 1) AS t 
    ORDER BY SCORE DESC
    
  • Попробуйте увеличить sort_buffer_size в my.conf, чтобы ускорить эти файловые хранилища.

Ответ 2

Я знаю, что этот вопрос старый, но я недавно столкнулся с этой проблемой, и решение, которое я придумал, заключалось в использовании производной таблицы. В производной таблице создайте свой расчетный столбец. Во внешнем запросе вы можете заказать его. Кажется, он работает значительно быстрее для моей рабочей нагрузки (на порядок).

SELECT value1, value3
FROM (
    SELECT value1, (value2 * an_arbitrary_float) as value3 
    FROM sometable 
    WHERE id = 1 
) AS calculated
ORDER BY value3

Ответ 3

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