Эффективно выполнять сложные MySQL запросы - PullRequest
1 голос
/ 28 октября 2019

Проблема

Учитывая запрос пользователя Q на веб-странице, я пытаюсь вычислить следующую несколько сложную функцию для каждой сущности p в моей базе данных:

enter image description here

(D также зависит от пользовательского запроса Q) В моей базе данных примерно 440 000 p сущностей, каждая из которых имеет в среднем ~ 50 связанных w_{d,p} веса и ~ 400 связанных u_{p, c} весов. Прямо сейчас эти веса хранятся в трех таблицах, и есть дополнительная таблица, которая определяет отношения между d и c:

table              columns                indices
-----              -------                ----
w weights:         p | d | w_pd           primary key (p, d), index on d
u weights:         p | c | u_pc           primary key (p, c), index on c
v weights:         c | v_c                primary key c
d/c relationship:  d | c                  primary key (d, c), index on c

Идентификаторы p, d и c - все варианты, размер которых варьируется от 10 до 16. w_dp, u_pc и v_c являются числами с плавающей точкой.

Мой нынешний подход к вычислению вышеприведенного уравнения предусматривает несколько объединений, подзапросов, операторов по группам и т. Д. В зависимости от Q мы можемиметь возможность обрезать набор интересующих нас p сущностей до более управляемого числа, и вычисление может занять всего несколько секунд. Но некоторые значения Q приводят к вычислению, которое занимает несколько минут.

Пример вычисления

Предположим, у нас есть следующие четыре таблицы:

d/c relationship   w weights           u weights        v weights
d  | c             p  | d  | w_dp      p  | c  | u_pc   c  | v_c 
d1 | c1            p1 | d1 | 1         p1 | c1 | 6      c1 | 12
d1 | c2            p1 | d2 | 3         p1 | c2 | 8      c2 | 16
d2 | c2            p2 | d1 | 2         p2 | c1 | 11     c3 | 15
d3 | c3            p3 | d2 | 4         p3 | c2 | 7
                   p3 | d3 | 5         p3 | c3 | 9
                   p4 | d3 | 10        p4 | c1 | 13

Запрос *На самом деле 1040 * - это набор c идентификаторов, который ограничивает набор D, в котором сумма окончена. Итак, скажем Q = {c1, c2}. Используя таблицу отношений d / c, наша сумма будет больше d1 и d2. Вычисляя сумму для p1, мы имеем:

d1: 1 * max(6, 8) * [v_c : c = argmax_c (u_11=6, u_12=8)] = 1 * 8 * 16 = 128
d2: 3 * max(8) * [v_c : c = argmax_c (u_12=8)] = 3 * 8 * 16 = 384

Таким образом, оценка для p1 составляет 128 + 384 = 512. Мы сделали бы аналогичные вычисления для p2 и p3. p4 связан только с d3, а d3 не имеет отношения к Q = {c1, c2}, поэтому нам нечем суммировать p4.

Вопрос

Есть лиразумный способ быстро вычислить вышеуказанную функцию? В частности,

  1. Используете существующую схему БД? Насколько я понимаю, использование агрегатных функций над объединенными таблицами, как я сейчас делаю, довольно медленное, поэтому я предполагаю, что ответом на этот вопрос будет «нет».

  2. Использование альтернативной таблицыструктура? Моя единственная текущая идея - объединить веса w / u / v в одну массивную таблицу строк длиной ~ 700 м и использовать эту таблицу для запроса. Я не уверен, насколько это будет полезно, но, может быть, правильная индексация может быть быстрее.

  3. Должен ли я сделать что-то еще полностью? Есть ли альтернативный инструмент для хранения / обработки данных, который я должен рассмотреть?

Поскольку я очень начинающий, когда дело доходит до SQL, я надеялся получить более четкое представление о направлении, прежде чемЯ трачу слишком много времени на тупик.

Обновление

Я знаю, что это не получило большой тяги, но для будущих зрителей: способ, которым я решил это, был, делая все вычисления передвремя. Существует около 5000 возможных запросов q и максимум ~ 500 000 объектов p. В результате получится таблица размером 2,5 миллиарда строк, где (p, q) - это первичный ключ. В действительности, для каждого запроса q в среднем присваивается только примерно 75 000 объектов, что приводит к чуть более управляемому размеру таблицы 75000 * 5000 = 375 000 000. Теперь, во время запроса, все, что мне нужно сделать, чтобы получить соответствующий список оценок, это фильтр на q, что намного проще, чем делать это сумасшедшее суммирование.

Тем не менее, если кто-то увидит это и внесет свой вклад, я все равно хотел бы услышать мнение любых экспертов по SQL / MySQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...