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" - количество пар с этим расстоянием.

0 ответов

Другие вопросы по тегам