Как заполнить пробелы идентичности при вставке данных на SQL Server? - PullRequest
0 голосов
/ 17 мая 2019

Прежде всего я хотел бы сказать, что я знаю, почему и как работает функция SQL Identity, кэшируя значения идентификаторов, которые будут использоваться, и что она не должна быть без пропусков. Таким образом, после перезапуска сервера (например) он может перескакивать 1000/10000 значений в зависимости от типа данных идентификации , и я знаю, что идентификация должна быть бессмысленной.

Тем не менее, много лет назад я разработал средство сокращения ссылок для старой версии SQL Server, которая не вела себя так, как описано выше. Это средство сокращения ссылок использует столбец Id для создания сокращенной части URL.

После обновления версии SQL Server стали появляться пробелы.

Таблица, содержащая ссылки для сокращения, похожа на следующую (обратите внимание на пробелы):

Id     | Url
---------------------------------
1      | http://foo.bar
2      | http://bar.foo     
10001  | http://google.com
20001  | http://stackoverflow.com

Мое приложение затем сокращает вышеуказанные ссылки следующим образом (это не таблица базы данных):

Id     | ShortenedUrl
---------------------------------
1      | foo.bar/a 
2      | foo.bar/b
10001  | foo.bar/fZ2sh
20001  | foo.bar/bbSz1

(просто чтобы проиллюстрировать, алгоритм не такой простой, как 1 = a, 2 = b)

Так что теперь у меня есть проблема: весь смысл в укорочении ссылок заключается в создании коротких ссылок. Теперь у меня на 4 символа больше, чем необходимо.

Я не могу просто использовать функцию row_number() OVER (ORDER BY [ID]), потому что у меня уже есть производственные данные, которые могут быть потеряны / сгенерированы.

Каковы мои возможности в отношении способов использования пробелов при создании следующих сокращенных ссылок?

Дополнительная информация:

Я могу создать еще один столбец, который импортирует данные из столбца Id (для уже существующих) и начинает использовать новую логику с помощью процедуры (вызываемой для вставки данных), блокирующей все, что необходимо заблокировать, чтобы получить следующий доступный пробел номер для новых строк.

Эта таблица в настоящее время используется только в приложении MVC (внешние ключи не указывают на нее). Данные в настоящее время вставляются через прямые вставки, но я могу обновить приложение, чтобы использовать (новую) процедуру. Другими словами, структура таблицы может изменяться, информация, содержащаяся в них, не может.

1 Ответ

0 голосов
/ 17 мая 2019

Одним из вариантов является замена идентификатора последовательностью . Вам все еще нужно будет исправить неверные данные, но это позволяет отделить URL-адрес от ключа.

Но из того, что я вижу, существующий укорочитель нуждается в некоторой работе.
При хорошем алгоритме для значения 20001 нет причин требовать более 3 символов.
Если вы используете два дополнительных «специальных» символа, вы можете получить до 64 возможных значений для каждого символа в сокращенном URL-адресе (AZ, az, 0-9 и наши специальные значения. И _), что достаточно для хранения шести битов данных. , У нас уже есть кодировка base-64 таким образом, но поскольку у вас есть только цифры, вы можете получить еще более эффективную.

Возьмите число типа 20001, преобразуйте его в двоичный код:

100111000100001

Заполните нули слева, чтобы число двоичных цифр было кратно шести:

000100111000100001

Разбейте его на группы по шесть:

000100  111000   100001

Каждая из этих групп должна соответствовать одному возможному символу. Чтобы получить исходный номер ID, сделайте то же самое в обратном порядке.

С этой схемой вы получите 262143, прежде чем вам нужно будет добавить 4-й символ в ваши URL, 16777215, прежде чем добавить 5-й символ, и 1073741823, прежде чем вы добавите 6-й.

Для забавы вот код C # для преобразования:

private static char[] charMap = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                                 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
                                 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
                                 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
                                 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
                                 'y', 'z', '.', '_'};

public static string GetURLKey(int id)
{
    if (id <= 0) return "0";

    var bt = new byte[32];
    int pos = 32;
    while (id > 0)
    {
        pos--;
        bt[pos] = (byte)(id % 2);
        id >>= 1;
    }
    var bts = new Span<byte>(bt, pos, 32-pos);

    var r = 6 - (bts.Length % 6);
    if (r == 6) r = 0;

    return string.Create((bts.Length + r) / 6, bts.ToArray(), (span, arr) =>
    {
        int curChar = 0, charPos = r, bitArrPos = 0, curVal = 0;

        while (bitArrPos < arr.Length)
        {
            while (bitArrPos < arr.Length && charPos < 6)
            {
                curVal *= 2;
                curVal += (int)arr[bitArrPos];

                bitArrPos++;
                charPos++;
            }
            span[curChar] = charMap[curVal];
            curVal = 0;
            charPos = 0;
            curChar++;
        }

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