Вход | Регистрация
    1  2  3  4  5

Прошу проверить код

Прошу проверить код
Я
   H A D G E H O G s
 
27.04.21 - 21:00
Дня доброго.
Есть задача собрать хеш с данных, записать его в 1С и выполнять поиск по нему.
Хеш я решил собрать MD5, проверил на 15 млн. записей, коллизий не нашел.
MD5 - это 16 байт и я их отлично засуну в УникальныйИдентификатор 1С и проиндексирую.
В виде строки это будет 32 символа, 64 байта в данных и такое хранение хеша и его индекса нам и вообще не нужно.

Новый ХешированиеДанных(MD5) возвращает хеш в виде ДвоичныхДанных, которые мне надо преобразовать в UUID.
Делаю я это так:

Функция ПреобразоватьДвоичныеДанныеВУникальныйИдентификатор(Данные) Экспорт
    Если Данные.Размер()<>16 Тогда //В уникальном идентификаторе должно быть 16 байт
        Возврат Неопределено;
    КонецЕсли;
    БуферДвоичныхДанныхХеша=ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Данные); // 16 байт
    
    D1=БуферДвоичныхДанныхХеша.ПолучитьСрез(0,4); // 4 первых байта
    D1=D1.Перевернуть(); // hex требует bigEndian
    D2=БуферДвоичныхДанныхХеша.ПолучитьСрез(4,2); // 2 вторых байта
    D2=D2.Перевернуть();
    D3=БуферДвоичныхДанныхХеша.ПолучитьСрез(6,2); // 2 третьих байта
    D3=D3.Перевернуть();
    D4=БуферДвоичныхДанныхХеша.ПолучитьСрез(8);   // 8 байт остатка
    D40=D4.ПолучитьСрез(0,1);
    D41=D4.ПолучитьСрез(1,1);
    D42=D4.ПолучитьСрез(2,1);
    D43=D4.ПолучитьСрез(3,1);
    D44=D4.ПолучитьСрез(4,1);
    D45=D4.ПолучитьСрез(5,1);
    D46=D4.ПолучитьСрез(6,1);
    D47=D4.ПолучитьСрез(7,1);
    
    D1=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D1);
    D2=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D2);
    D3=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D3);
    D40=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D40);
    D41=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D41);
    D42=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D42);
    D43=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D43);
    D44=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D44);
    D45=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D45);
    D46=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D46);
    D47=ПолучитьHexСтрокуИзБуфераДвоичныхДанных(D47);
    ИдентификаторСтрокой=D1+"-"+D2+"-"+D3+"-"+D40+D41+"-"+D42+D43+D44+D45+D46+D47;
    Возврат Новый УникальныйИдентификатор(ИдентификаторСтрокой);    
КонецФункции
   H A D G E H O G s
 
401 - 02.05.21 - 15:07
"Ветерок раскачивает чувств качель
И такая горечь.
А любовь моя - печаль-виалончель
И на ней хреначит мертвый Ростропович."

Я в расстроенных чувствах, короче.

1С вычисляет хеш для 100000 150 символов за 8,6 секунд.
Дельфи делает это за 250 мсек.

Буду переносить в ВК, наверное.
   Garykom
 
402 - 02.05.21 - 15:53
(401) Потеряешь на передаче в ВК
Выноси уже наружу и хранение
   H A D G E H O G s
 
403 - 02.05.21 - 21:23
846 мс с использованием ВК.

Обмен через кусок текста в виде строковой переменной в 100000 строк, разделенного переносами строк
250 мсек - MD5
164 мсек - MD5 в TGUID
26  мсек - разборка входящего текста и сборка исходящего текста и передача в ВК/из ВК

406 мсек - сборка в 1С массива в единый текст и разбор результата в массив и преобразование в УникальныйИдентификатор
   ДедМорроз
 
404 - 02.05.21 - 23:56
(401) попробуй тот же самый хэш вычислять,не копируя строки,т.к.тормоза будут как раз на копировании строк.
Я когда md5 на другие языки переписывал (например,на vbscript), как раз с копированием строк боролся,т.к.это самые медленные операции.
   Кирпич
 
405 - 03.05.21 - 11:51
(403) Пакуйте хеши в 16 символьный китайкод и будет вам в 1с миллион за 8 сек
Функция MD5КитайКод(Стр)
    Хеш = Новый ХешированиеДанных(ХешФункция.MD5);
    Хеш.Добавить(Стр);
    Возврат ПолучитьСтрокуИзДвоичныхДанных(Хеш.ХешСумма, "UTF-16LE");
КонецФункции

   Кирпич
 
406 - 03.05.21 - 11:54
ой. 8 символьный даже
   H A D G E H O G s
 
407 - 03.05.21 - 11:59
(405) гениально!
   Кирпич
 
408 - 03.05.21 - 12:00
(407) А чо. Те же 16 байт, только без лишних движений по склеиванию строк для формирования GUID
   H A D G E H O G s
 
409 - 03.05.21 - 12:02
(408) нет, я наоборот респектую.
   H A D G E H O G s
 
410 - 03.05.21 - 12:16
(408) надо еще понять что будет с нулевым символом
   Кирпич
 
411 - 03.05.21 - 12:21
(410) А что с ним?
   H A D G E H O G s
 
412 - 03.05.21 - 12:38
(411) его наличие обычно трактуется как завершение строки
   Кирпич
 
413 - 03.05.21 - 12:42
(412) Ну да. Два нуля подряд должно быть. А чо попадалось такое?
   Кирпич
 
414 - 03.05.21 - 12:50
(412) А ты попробуй. Сделай какой нибудь FFFF0000AAAA1111
   Кирпич
 
415 - 03.05.21 - 12:55
Всё нормально.
    Данные = ПолучитьДвоичныеДанныеИзHexСтроки("0000222200003333");
    Стр = ПолучитьСтрокуИзДвоичныхДанных(Данные, "UTF-16LE");
    Сообщить(Стр);
    Данные = ПолучитьДвоичныеДанныеИзСтроки(Стр, "UTF-16LE");
    Стр = ПолучитьHexСтрокуИзДвоичныхДанных(Данные);
    Сообщить(Стр);

   Кирпич
 
416 - 03.05.21 - 12:57
Только как оно в БД будет не проверял. Может там сюрпрайз от 1с какой нибудь
   Кирпич
 
417 - 03.05.21 - 12:58
Но вряд ли
   Кирпич
 
418 - 03.05.21 - 13:10
Всё работает
    Данные = ПолучитьДвоичныеДанныеИзHexСтроки("0000222200003333");
    Стр = ПолучитьСтрокуИзДвоичныхДанных(Данные, "UTF-16LE");
    Эл = Справочники.Справочник1.СоздатьЭлемент();
    Эл.Наименование = Стр;
    Эл.Записать();
    Ссылка = Справочники.Справочник1.НайтиПоНаименованию(Стр,Истина);
    Если Ссылка <> Справочники.Справочник1.ПустаяСсылка() Тогда
        Данные = ПолучитьДвоичныеДанныеИзСтроки(Ссылка.Наименование, "UTF-16LE");
        Стр = ПолучитьHexСтрокуИзДвоичныхДанных(Данные);
        Сообщить(Стр);
    Иначе
        Сообщить("Не нашел");
    КонецЕсли;
        

   Кирпич
 
419 - 03.05.21 - 13:12
А не. Глючит когда пытаешься справочник посмотреть. Недопустимые символы говорит
   Кирпич
 
420 - 03.05.21 - 13:14
И если символы 00 в конце, то дальше не читает. Но это можно победить принудительным добавлением двух нулей справа
   Кирпич
 
421 - 03.05.21 - 13:15
Хотя нет. С нулями в конце облом будет тоже
   Кирпич
 
422 - 03.05.21 - 13:24
Разве что добавлять FFFF в конце. Но это уже не красиво
   H A D G E H O G s
 
423 - 03.05.21 - 13:49
(419) Ну мы это поле выводить не будем и всё
   Кирпич
 
424 - 03.05.21 - 13:56
Да и без китайкода в виде HEX строки тоже вполне приемлимо. 32 байта.
   Кирпич
 
425 - 03.05.21 - 13:56
Или там 64 получается :))
Мля. Лучше уж в идентификаторах тогда.
   Garykom
 
426 - 03.05.21 - 15:03
Надеюсь вы понимаете что https://i2.paste.pics/6ef1f3ce66bd4cccfb41c2e92a0cb8ae.png
   Кирпич
 
427 - 03.05.21 - 15:41
Да и с идентификаторами нормально работает. Миллион идентификаторов из хешей за 15 сек
Функция MD5Идентификатор(Стр)
    Хеш = Новый ХешированиеДанных(ХешФункция.MD5);
    Хеш.Добавить(Стр);
    Д = ПолучитьHexСтрокуИзДвоичныхДанных(Хеш.ХешСумма);
    Д = СтрШаблон("%1-%2-%3-%4-%5", Сред(Д,1,8), Сред(Д,9,4), Сред(Д,13,4), Сред(Д,17,4), Сред(Д,21,12));
    Возврат Новый УникальныйИдентификатор(Д);
КонецФункции

   Почему 1С
 
428 - 04.05.21 - 08:04
Про производительность можно даже не задумываться, у вас что там каждый день по миллиону марок уходит, если нет, то на что разница в 10 сек раз в день может повлиять.
   fisher
 
429 - 05.05.21 - 09:35
(396) > Объясните для тупых (для меня), почему китайская раскладка 1 символ занимает 1 байт в SQL
Суть проблемы - нужно эффективно хранить двоичные данные и искать по ним.
Но. В 1С нет индексируемых типов для двоичных данных кроме уникального идентификатора.
Если писать символьное представление двоичных данных, то размер удваивается, так как в mssql юникодные символы занимают минимум 2 байта (для упрощения обработки UTF-8 там не используется).
Поэтому идея была в том, чтобы писать в строку не символьное представление двоичных данных, а непосредственно сами двоичные данные.
Берется по два байта двоичных данных, а в строку пишется тот символ, кодом которых эти два байта двоичных данных выступают. При этом часто (но не всегда) получаются символы с иероглифических кодовых страниц (так как их там дохрена).
   fisher
 
430 - 05.05.21 - 09:43
Меня этот подход по-прежнему смущает. Что в очень редких случаях, когда получится код суррогатной пары или какой-то зарезервированной области, то могут быть проблемы. Но тесты на реальных данных вроде показывают что такой проблемы нет. Но осадочек все равно висит :)
 
 
   Кирпич
 
431 - 05.05.21 - 10:14
(430) Так проверь и спи спокойно. Запиши и прочитай в справочник или в регистр сведений китайкод всех вариантов от '00' до 'ZZ' (в марках вроде кроме латинских буков и цифр ничего не используется)
   Кирпич
 
432 - 05.05.21 - 10:17
код 'ZZ' 23130 
23130 символов перебрать
   fisher
 
433 - 05.05.21 - 10:49
(431) Согласен. Примерно так бы я и сделал.
   Кирпич
 
434 - 05.05.21 - 10:50
А если брать только буквы и цифры, то там вабще 36*36 и всё читабельное (китай галимый в основном)
   Кирпич
 
435 - 05.05.21 - 10:51
    Буки = "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";
    Массив = СтрРазделить(Буки," ");
    КитайМассив = Новый Массив;
    Для а1 = 0 по Массив.ВГраница() Цикл
        Для а2 = 0 по Массив.ВГраница() Цикл
            Буфер = ПолучитьБуферДвоичныхДанныхИзСтроки(Массив[а2]+Массив[а1],"US-ASCII");
            КитайМассив.Добавить(ПолучитьСтрокуИзБуфераДвоичныхДанных(Буфер,"UTF-16LE"));
        КонецЦикла;
    КонецЦикла;
    Сообщить(КитайМассив[0]);

   Кирпич
 
436 - 05.05.21 - 10:52
Глянь в отладчике КитайМассив. Всё читабельное, красивое и китай-тамильское
  1  2  3  4  5

Список тем форума
 
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.