LINUX.ORG.RU

Сравниваем строки с Юлией Высоцкой

 ,


1

3

Имеется таблица:

create table t (
    "path" text primary key,
    ...
);

Безо всяких там переопределённых collation, дефолтное collation базы – en_US.utf8, connection charset – тоже UTF8.

В таблице этой есть строка со значением path = '/private/auto_test_intern/U3.json' (зуб даю, значение именно такое: 33 байта, все символы – в обычном ASCII).

Делаем:

-- отдаёт 1 строку; length = 33:
select length("path"::bytea), * from t where "path" like '/private/auto_test_intern/U3.json'; 

-- 0 строк:
select * from t where "path" = '/private/auto_test_intern/U3.json';

-- 1 строка:
select * from t where "path" like '/private/auto_test_intern/U3.json' and substr("path", 1, 33) = '/private/auto_test_intern/U3.json';

Вопрос: ЧЗНх во втором запросе?!



Последнее исправление: pr849 (всего исправлений: 4)
Ответ на: комментарий от anonymous

Спасибо, помогло:

reindex table t;

Индекс, разумеется, есть: это ж PK. Мысль такая пробегала, но как-то не задержалась: это ж что должно случиться в транзакционной СУБД, чтобы индекс побился.

pr849
() автор топика
Ответ на: комментарий от pr849

что должно случиться в транзакционной СУБД, чтобы индекс побился.

Ищи причину, для начала проверяй аппаратуру - оперативку, файловую систему, жесткий диск/ssd.
Reset'ы были??

Atlant ★★★★★★★★
()
Ответ на: комментарий от Atlant

Товарищи на созвоне говорят, что не исключено, что косяк возник из-за переноса базы (хз откуда куда, я в ихних инфраструктурных игрищах не участвую). Интересно, возможно ли такое при backup/restore – в процессе restore индексы временно задизаблены, а по завершении restore не построились. (Впрочем, не настолько интересно, чтобы гуглить.)

pr849
() автор топика
Ответ на: комментарий от vbr

Лучше бы рассказали, как такое вообще может быть на исправном железе, чтобы индекс сломался. Я прочитал эту тему и мне стало страшно.

Никак не может, для этого нужно его явно сломать. Выше написано что такое получилось при переносе базы с отключением перестроения индексов. Что-то там менялось в collation, уж не помню при переезде на новую версию постгреса, или это с системной collation было связано, соответственно логический порядок сравнения строк менялся, из-за этого индексы, если их не перестроить, неправильно работали. Но про миграцию этого кейса было на каждом углу написано.

anonymous
()
Ответ на: комментарий от Obezyan

не надо так делать

При такой безапелляционной формулировке - вон из профессии. Текстовые PK - самое обычное дело, в общем случае их применимость зависит от задачи конечно же.

anonymous
()
Ответ на: комментарий от anonymous

При такой безапелляционной формулировке - вон из профессии.

закукарекал анонимус, выгоняйте обезъяна, пробуйте.

Текстовые PK - самое обычное дело

для недоучек

теперь обоссу вас по пунктам:

  1. Безапелляционная формулировка - это «никогда не при каких обстоятельствах не смейте так делать», что отличается от «не надо так делать».

  2. В подавляющем большинстве случаев текстовые PK это результат непродуманной архитектуры БД из-за недостатка знаний и опыта. PK практически во всех базах данных является ссылкой на конкретные данные в таблице поэтому использование строковых ключей большой длины работает медленнее и жрет больше памяти при прочих равных. Причем чем больше база тем хуже работает. Простое правило - чем меньше ключ тем быстрее запрос. Вот полнотекстовые индексы это вполне нормальное явление, а текстовые первичные ключи - нет, если мы говорим не о студенческой лабе на 1000 записей.

Обеткайте, следующий.

Obezyan
()
Ответ на: комментарий от Obezyan

Безапелляционная формулировка - это «никогда не при каких обстоятельствах не смейте так делать», что отличается от «не надо так делать».

Пока ты не написал «как правило» или «в большинстве случаев», никакой разницы нет, котик. На самом деле так даже хуже - если бы ты написал «никогда не при каких обстоятельствах не смейте так делать» все бы сразу поняли что ты дурачок и слушать не стали, а «не надо» же примут за чистую монету и повторять будут.

В подавляющем большинстве случаев

Вот ты и дал заднюю. И почему же ты сразу так не сказал?

это результат непродуманной архитектуры БД из-за недостатка знаний и опыта

Такое исключать, конечно, нельзя, как и любую другую дичь, но я считаю что именно «в большинстве случаев» это таки результат того что данные должны индексироваться по строковому ключу.

PK практически во всех базах данных является ссылкой на конкретные данные в таблице поэтому использование строковых ключей большой длины работает медленнее и жрет больше памяти при прочих равных

Чем что? Для данных которые естественным образом идентифицируются строкой, например домены, альтернативой текстовому ключу будет два индекса - искусственный serial pk и всё тот же текстовый, необходимость в котором никуда не делась, и который в роли вторичного индекса потребляет столько же ресурсов. Два индекса будут гарантировано жрать больше памяти и работать медленнее на запись.

А будет ли быстрее чтения по serial pk зависит, опять же, от кейса. Возможно их вообще не будет, если запросы приходят с тем же естественным ключом. Возможно они будут намного медленнее, потому что у текстовых индексов есть порядок (это значит, например, что сджойнить две таблицы по домену можно дешевейшим index (only) scan, вместо хэширований или сортировок) и локальность (это значит, например, что если хранить инвертированный домен и нам приходит пачка запросов на его поддомены, то чтобы их можно нужно поднять в память всего одну страницу индекса, а не тыкаться по всему диску). Возможно, конечно, и медленнее, если нужно приджойнить таблицу с нелокальными данными - он порядка строк мы ничего не выиграем, а от размера индекса проиграем. Или просто при случайных чтениях.

Причем чем больше база тем хуже работает

Это сбивающее с толку заявление, ибо асимптотика индекса не зависит от размера ключа, только константа меняется. «Чем больше база тем хуже работает» любой btree ключ.

а текстовые первичные ключи - нет, если мы говорим не о студенческой лабе на 1000 записей.

Только студенческие базы на 1000 записей ты и видел, если не встречал юзкейзов для text PK. Просвещайся, дорогой.

anonymous
()
Ответ на: комментарий от vbr

Ну я слишком старый и для меня первичный ключ это однозначность по которому можно прийти к нужной строке.

Не ну можно прийти к … что мол допускается, но это уже на самом деле изврат.

mx__ ★★★★★★★★★★★★
()
Ответ на: комментарий от vbr

collation не должен ни на что влиять вроде бы

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

asdpm
()
Ответ на: комментарий от vbr

я думаю это чушь и ничего не поломалось.

там или продвинутая collation которая зависит от системных библиотек, которые незаметно обновились и оно документировано сломалось (и всех уведомило ворнингами), или, как он говорит сам, «они переносили базу» так

asdpm
()
Ответ на: комментарий от vbr

обновлено

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

asdpm
()
Последнее исправление: asdpm (всего исправлений: 1)
Ответ на: комментарий от sin_a

Она совершенно точно не красивее строк с SSO в которые влезает sizeof() байт с учётом терминирующего \0. Она более похожа на COW строки с рефкаунтами - кому-то может и зайдёт, в целом же такое себе.

anonymous
()
Ответ на: комментарий от asdpm

А ещё должна быть вторая колонка с UUID, для внешних ссылок, чтобы враг не догадался. Особо продвинутые делают UUIDv7, чтобы он возрастал (типа индексы так компактней), но при этом их в душе гложут сомнения - достаточно ли это безопасно?

vbr ★★★★★
()
Ответ на: комментарий от vbr

о, uuid - это считается модно, продвинуто. замечал, что некоторые пока поступают проще: если хотят сгенерировать случайную hard-to-guess строку (зачем-то, для сесурити), то обязательно считают хеш-функцию. не важно от чего, можно от случайного числа или даже от колонки id (где сами знаете что). главное чтобы хеш. получившаяся шестандцатеричная букво-цифренная строка выглядит очень «шифровано», а вызов hash() в коде дает гораздо больше уверенности в сравнении вызовом randStr()

asdpm
()
Ответ на: комментарий от q137

Используйте субд oracle, такого там нет.

ню-ню «смеялись всем отделом» (с)

https://www.youtube.com/watch?v=w5YwKwxfyLQ

vtVitus ★★★★★★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 1)
Ответ на: комментарий от asdpm

Лучше уж так. Хуже у школьников думающих что они понимают принцип SQL, а потом мало того что это начинает жутко тормозить, так еще и работает не понятно как.

mx__ ★★★★★★★★★★★★
()