У меня есть таблица, которая для определенного (time, country, asn)
кортежа хранит несколько показателей:
+----------+---------+-------+-------+--------+--------+
| time | country | asn | rtt | rexb | reqs |
+----------+---------+-------+-------+--------+--------+
| 10000000 | US | 12345 | 40 | 0.05 | 5000 |
| 10000000 | US | 54321 | 120 | 0.15 | 500 |
| 10000000 | MX | 12345 | 300 | 0.25 | 1000 |
| 10000000 | MX | 54321 | 160 | 0.10 | 200 |
| .... | ... | ... | ... | .... | .... |
Во время общего использования я нормализую каждый из этих показателей до значения от 0 до 100, а затем возвращаю наибольшее значение, чтобы получить приблизительную оценку "насколько хорошо" соединение с этим ASN в этой стране:
SELECT
country,
asn,
least(
-- least(100, greatest(0, ...)) = clip value between 0 and 100
least(100, greatest(0,
-- normalize and protect against null values
-- sample normalization:
-- 0 ms RTT = "100% good"
-- 300 ms RTT = "0% good"
coalesce((300 - rtt) / 3, 0)
)),
least(100, greatest(0,
-- sample normalization:
-- 0% REXB = "100% good"
-- 50% REXB = "0% good"
coalesce((0.5 - rexb) / 0.5, 0)
)),
-- Other metrics may follow
) as quality
FROM
metrics
WHERE
time = 10000000 -- "current time"
Иногда я могу выполнять взвешенные средние значения, используя reqs
(количество запросов в этой стране + ASN) для взвешивания:
SELECT
country,
least(
least(100, greatest(0,
coalesce((300 - sum(rtt*reqs)/sum(reqs)) / 3, 0)
)),
least(100, greatest(0,
coalesce((0.5 - sum(rexb*reqs)/sum(reqs)) / 0.5, 0)
))
) as avg_quality
FROM
metrics
WHERE
time = 10000000 -- "current time"
GROUP BY
country
Этот запрос работает отлично. Однако я столкнулся с проблемой, когда попытался использовать ее в подзапросе.
Моя цель состояла в том, чтобы определить, сколько стран имеет "среднее качество" ниже определенного порога:
SELECT
count(*)
FROM (
SELECT
country,
least(
least(100, greatest(0,
coalesce((300 - sum(rtt*reqs)/sum(reqs)) / 3, 0)
)),
least(100, greatest(0,
coalesce((0.5 - sum(rexb*reqs)/sum(reqs)) / 0.5, 0)
))
) as avg_quality
FROM
metrics
WHERE
time = 10000000 -- "current time"
GROUP BY
time, country
) t1
WHERE t1.avg_quality < 50
Это породило ошибку:
ERROR 1815 (HY000): Internal error: Lost connection to ExeMgr. Please contact your administrator
Я могу выполнить более простые подзапросы без проблем. Почему это не удается, и как я могу это исправить?
Я использую MariaDB, а таблица metrics
использует механизм ColumnStore.
Когда я заменяю WHERE t1.avg_quality < 50
с WHERE country = "US"
запрос выполняется без проблем. Таким образом, он не имеет проблем с выполнением подзапроса или фильтрации. Это строго, когда я пытаюсь фильтровать на вычисленном столбце, что он терпит неудачу.
Я обратился к администраторам баз данных в моей компании, чтобы узнать, есть ли у них какие-либо ответы или предложения. Они не смогли дать объяснение поведению, но они смогли обеспечить обход:
SELECT
count(*)
FROM (
SELECT
country,
least(
least(100, greatest(0,
coalesce((300 - sum(rtt*reqs)/sum(reqs)) / 3, 0)
)),
least(100, greatest(0,
coalesce((0.5 - sum(rexb*reqs)/sum(reqs)) / 0.5, 0)
))
) as avg_quality
FROM
metrics
WHERE
time = 10000000 -- "current time"
GROUP BY
time, country
HAVING
avg_quality < 50
) t1