Как оптимизировать ORDER BY для вычисляемого столбца в таблице MASSIVE MySQL - PullRequest
13 голосов
/ 03 августа 2010

У меня очень большая (более 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.Затем я хочу ORDER BY по этому вычисленному столбцу 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 с

- РЕДАКТИРОВАТЬ -

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

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

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 довремя

Ответы [ 3 ]

3 голосов
/ 04 августа 2010

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

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

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

2 голосов
/ 26 января 2013

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

SELECT value1, value3
FROM (
    SELECT value1, (value2 * an_arbitrary_float) as value3 
    FROM sometable 
    WHERE id = 1 
) AS calculated
ORDER BY value3
0 голосов
/ 03 августа 2010

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

...