Создать совокупную контрольную сумму столбца - PullRequest
9 голосов
/ 26 февраля 2009

Я хочу вычислить контрольную сумму всех значений столбца в совокупности.

Другими словами, я хочу сделать некоторый эквивалент

md5(group_concat(some_column))

Проблема с этим подходом:

  1. Это неэффективно. Он должен объединить все значения столбца в виде строки во временном хранилище, прежде чем передать его в функцию md5
  2. group_concat имеет максимальную длину 1024, после чего все остальное будет усечено.

(Если вам интересно, вы можете убедиться, что конкат значений находится в непротиворечивом порядке, однако, верьте этому или нет, group_concat () принимает в нем порядок за предложением, например, group_concat(some_column order by some_column))

MySQL предлагает нестандартные побитовые агрегатные функции BIT_AND (), BIT_OR () и BIT_XOR (), которые, как я полагаю, были бы полезны для этой проблемы. В этом случае столбец числовой, но мне было бы интересно узнать, есть ли способ сделать это с помощью строковых столбцов.

Для этого конкретного приложения контрольная сумма не должна быть криптологически безопасной.

Ответы [ 4 ]

5 голосов
/ 15 апреля 2013

Следующий запрос используется в инструменте Percona Mysql Table Checksumming. Это немного сложно понять, но по сути это CRC32 s столбец (или связка столбцов) для каждой строки, затем XOR s объединяет их вместе с помощью групповой функции BIT_XOR Если один хэш crc отличается, результат XOR будет также другим. Это происходит в фиксированной памяти, поэтому вы можете проверять суммы произвольно больших таблиц.

SELECT CONV(BIT_XOR(CAST(CRC32(column) AS UNSIGNED)), 10, 16)

Следует помнить одну вещь: это не предотвращает возможные столкновения, и CRC32 - довольно слабая функция по сегодняшним стандартам. Более приятная функция хеширования будет выглядеть как FNV_64. Было бы очень маловероятно иметь два хэша, которые дополняют друг друга, когда XOR объединены.

3 голосов
/ 26 февраля 2009
SELECT  crc
FROM
(
  SELECT @r := MD5(CONCAT(some_column, @r)) AS crc,
         @c := @c + 1 AS cnt
  FROM
    (
    SELECT @r := '', @c := 0
    ) rc,
    (
    SELECT some_column
    FROM mytable
    WHERE condition = TRUE
    ORDER BY
      other_column
    ) k
) ci
WHERE cnt = @c
3 голосов
/ 27 февраля 2009

Похоже, вы могли бы также использовать crc32 вместо md5, если вас не волнует криптографическая стойкость. Я думаю это:

select sum(crc32(some_column)) from some_table;

будет работать со строками. Это может быть неэффективно, так как, возможно, MySQL создаст временную таблицу (особенно если вы добавили order by).

1 голос
/ 26 февраля 2009

Если столбец числовой, вы можете сделать это:

SELECT BIT_XOR(mycolumn) + SUM(mycolumn)

Конечно, это легко победить, но оно будет включать все биты в столбце.

...