PostgreSQL фиксирует приращение UPDATE
Я не знаю, как правильно назвать название вопроса, но это будет понятно прямо ниже. Я новичок в PostgreSQL и вопрос может быть немного глупым.
У меня есть таблица с именем "hash", которая имеет "id" (bigint) и "val" - тип bytea длиной 100 бит. Количество записей составляет около 20 миллионов. Я хочу знать распределение расстояний Хэмминга (гистограмма) между всеми записями (или 1-0,1 % из них). Мне нужна таблица с именем "hist", которая будет иметь "id" - расстояние Хемминга и "num" - количество пар из "hash", которые имеют расстояние, равное его "id". Таким образом, таблица "hist" будет иметь 800 строк с "id" от 0 до 800 (минимальное и максимальное расстояние Хэмминга между парой из 100 битов равно 0 и 800) и "num" - количество пар. Я сделал этот запрос для вставки значений:
UPDATE hist SET num=num+1 FROM
(
SELECT bit_distance(hash,E'\\xffcfff') AS dist FROM hash
)
AS sub WHERE id = sub.dist
Так что "bit_distance" - функция, которая берет 2 байта и возвращает int. Все хорошо, но проблема в том, что "num" в "hist" равно 0 или 1. Это плохо, потому что после этой транзакции (как я думал) "num" во многих столбцах должно быть больше 1. Я fink проблема в том, что "SET num=num+1" сохраняется в строковые единицы в конце транзакции, и это будет "1=0+1" (0 в начале). Поэтому мне нужно как-то зафиксировать "SET num=num+1" во время выполнения запроса.
Я попытался поместить "SET num=num+1" в цикл FOR. Это сделало то, что я хочу, но производительность была очень медленной - 20 минут против 0,8 с для моего первого запроса (у меня есть таблицы "hash" и "hist", подключенные к ram)
Я пытался посчитать числа для подзапроса
UPDATE hist SET num=num+sub.ds FROM
(
SELECT COUNT(dist) as ds from
(
SELECT bit_distance(hash,E'\\xffcfff') AS dist FROM hash
)
GROUP BY dist
)AS sub
WHERE id = sub.dist
Но запрос выполнит сканирование и последующую сортировку для всех 20-метровых записей, что довольно медленно.
Есть ли способ сделать это быстрее?
PS Есть некоторые ошибки в моем sql, потому что он опубликован из моей памяти. Но я надеюсь, что они не мешают понять общий смысл.
PPS Я также буду благодарен, если кто-то может поделиться ссылкой на хорошее руководство по написанию расширений GIST на языке C (мне нужно построить индекс по расстоянию Хэмминга).
ОБНОВЛЕНО для запроса @a_horse_with_no_name Например, у меня есть таблицы:
+----------------+ +----------------+
| hash | | hist |
+----------------+ +----------------+
| id val | | id num |
+----------------+ +----------------+
| 1 , E'\\0001'| | 1, 0 |
| 2 , E'\\0001'| | 2, 0 |
| 3 , E'\\0003'| | 3, 0 |
| 4 , E'\\0003'| | ... |
| 5 , E'\\0003'| | 16, 0 |
+----------------+ +----------------+
Я хочу получить гистограмму для расстояния Хемминга "beetwean" имеет " "val"и, например, E'\0000'. Выход будет:
+----------------+ +----------------+
| hash | | hist |
+----------------+ +----------------+
| id val | | id num |
+----------------+ +----------------+
| 1 , E'\\0001'| | 1, 2 |
| 2 , E'\\0001'| | 2, 3 |
| 3 , E'\\0003'| | 3, 0 |
| 4 , E'\\0003'| | ... |
| 5 , E'\\0003'| | 16, 0 |
+----------------+ +----------------+
E '\ 0001' расстояние Хэмминга E '\ 0000' = 1
E '\ 0003' расстояние Хэмминга E'\0000' = 2
В таблице "hist" an "id" - это расстояние, а "num" - количество пар с этим расстоянием.