2016-02-07 4 views
1

число, например:эффективно хранить десятичных чисел со многими ведущими Нули в Postgresql

0.00000000000000000000000000000000000000

трудно хранить без большой производительности штрафа с имеющимися числовыми типами в Postgres. Этот question адресует аналогичную проблему, но я не чувствую, что она дошла до приемлемого разрешения. В настоящее время один из моих коллег приземлилась на округление чисел, как это до 15 знаков после запятой и просто хранить их как:

0.000000000000001 

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

enter image description here

Поскольку мы храним десятки тысяч этих чисел и действующих на них, десятичный числовой тип не является хорошим вариантом для нас, как штраф производительность слишком велик.

Я ученый, и мой естественный склон был бы просто хранить эти типы чисел в научной нотации, но не кажется, что postgres обладает такой функциональностью. Мне действительно не нужна вся точность в числе, я просто хочу сохранить 4 цифры или около того, поэтому мне даже не нужны 15 цифр, которые предлагает тип чисел с плавающей точкой. Каковы преимущества и недостатки хранения этих чисел в двух областях, как это:

1.234 (real) 
-40 (smallint) 

, где это эквивалентно 1,234 * 10^-40? Это обеспечило бы ~ 32000 ведущих десятичных знаков с двумя байтами, используемыми для их хранения, и 4 байта для хранения реального значения, в общей сложности максимально 6 байтов на номер (дает мне точный номер, который я хочу сохранить, и занимает меньше места, чем существующее решение, которое потребляет 8 байтов). Похоже, что сортировка этих чисел будет значительно улучшена, так как вам нужно будет только отсортировать по полю smallint, а затем второе поле реального поля.

+1

Довольно уверен, что я не понимаю. Стандартный 8-байтовый формат IEEE для чисел с двойной точностью позволяет отображать очень маленькие числа как значение и показатель. Если вы можете жить с точностью до 15 цифр, почему бы просто не использовать формат двойной точности? – scottb

+0

@scottb Поскольку, как я уже упоминал в вопросе, округление всех моих результатов до 15-значной точности приводит к тому, что мои графики имеют четкую линию с такой точностью, поэтому, поскольку значение этих данных функционально эквивалентно, дисплей выглядит ужасно. – sage88

+0

Если ваши графики «выравниваются», более вероятно, что существует проблема с масштабированием ваших графиков или непреднамеренным литьем ваших значений в интегральные типы. Номера двойной точности IEEE способны отображать очень малые числа, вплоть до пределов точности, поскольку они очень большие. В частности, не должно быть преимуществ отдельно хранить значимость и показатель отдельно в вашей базе данных, как вы предлагали, поскольку это то, как внутренние числа двойной точности представлены внутри. – scottb

ответ

3

Вы и/или ваш коллега, похоже, смущены тем, какие числа могут быть представлены с использованием форматов с плавающей запятой.

A double precision (aka float) номер может хранить не менее 15 значащих цифр в диапазоне от примерно 1e-307 до 1e + 308.Вы должны думать об этом как о научной нотации. Удалите все нули и переместите их к экспоненте. Если то, что у вас есть в научной нотации, имеет менее 15 цифр и показатель между -307 и +308, его можно сохранить как есть.

Это означает, что 0.00000000000000000000000000000000000000 может быть сохранен как double precision, и вы сохраните все значимые цифры (123456). Не нужно округлять это до 0.000000000000001 или что-нибудь в этом роде.

Номера с плавающей запятой имеют хорошо известную проблему точного представления десятичных чисел (поскольку десятичные числа в базе 10 необязательно отображают десятичные числа в базе 2), но это, вероятно, не проблема для вас (это проблема, если вы должны иметь возможность делать точные сравнения по таким числам).

+0

Благодарим вас за помощь. Я, скорее всего, сделаю это правильным ответом. Поскольку @scottb уже заставил меня идти по правильному пути, я дам ему шанс сначала ответить, если он захочет, а затем выбрать ответ, который лучше всего подходит к этому. – sage88

+0

@ sage88, поэтому вам не нужно экономить место и не иметь до 32000 десятичных знаков, затем ...? – Ilya

0

Каковы преимущества и недостатки хранения этих чисел в два областях, как этот

Вы должны будете управлять 2 колонки вместо одного.

Грубо говоря, что вы будете делать, это экономить место, сохранив поплавки с более низкой точностью. Если вам нужны только 4 цифры точности, вы можете пойти дальше и сохранить еще 2 байта, используя smallint + smallint (1000-9999 + exponent). Используя этот формат, вы можете перерезать два маленьких символа в один 32-битный int (экспонент * 2^16 + мантисса), который тоже должен работать.

Предполагается, что вам необходимо сэкономить место для хранения и/или выходить за пределы экспоненциального значения с плавающей запятой +/- 308 цифр. Если это не так, стандартный формат в порядке.