Является ли хорошей идеей хранить атрибуты в целочисленном столбце и выполнять побитовые операции для их получения? - PullRequest
2 голосов
/ 10 августа 2010

В недавней статье CODE Magazine Джон Петерсен показывает, как использовать побитовые операторы в TSQL для хранения списка атрибутов в одном столбце таблицы БД.

Артикул здесь .

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

SELECT C.*   
FROM   dbo.Customers C  
       ,(SELECT 1   AS donotcontact   
               ,2  AS email   
               ,4  AS phone   
               ,8  AS fax   
               ,16 AS mail) AS contacttypes   
WHERE  ( C.contactmethods & contacttypes.email <> 0 )
AND    ( C.contactmethods & contacttypes.donotcontact = 0 )   

Затем он показывает, как инкапсулировать это в табличную функцию.

Вот мои вопросы:

1. Это хорошая идея? Есть ли недостатки? С какими проблемами я могу столкнуться, используя этот подход хранения атрибутов вместо хранения их в двух дополнительных таблицах (Customer_ContactType, ContactType) и соединения с таблицей Customer? Я думаю, одна проблема может быть, если мой список атрибутов становится слишком длинным. Если столбец является целым числом, тогда мой список атрибутов может быть не более 32.

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

Ответы [ 4 ]

2 голосов
/ 10 августа 2010

И не забывайте, что проблемы с техническим обслуживанием, вызванные этой техникой, могут стать причиной. Поскольку это не стандартно, все новые разработчики, вероятно, будут смущены кодом и не будут знать, как его правильно настроить. Ошибок будет предостаточно, и их будет сложно найти. Сложно также делать запросы типов отчетов из. Подобные хитрости почти никогда не являются хорошей идеей с точки зрения обслуживания. Это может выглядеть круто и элегантно, но все, что есть на самом деле - неуклюже и трудно работать со временем.

2 голосов
/ 10 августа 2010

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

Кроме того, просто нет 't any need - просто используйте битовый тип данных.

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

Если, однако, у вас есть столбец флагов,SQL-сервер совершенно не знает, сколько записей в таблице соответствует flags & 2 (электронная почта) - он не поддерживает индексы такого рода.Без такой информации SQL сервер с гораздо большей вероятностью выберет плохой план выполнения.

1 голос
/ 10 августа 2010

Одним из основных последствий для производительности является то, что не будет оператора поиска для индексов , который работает таким образом. Если бы вы сказали WHERE contact_email=1, возможно, в этом столбце есть индекс, и запрос будет использовать его; если бы ты сказал WHERE (contact_flags & 1)=1, то не стал бы.

** В одном столбце хранится только одна часть информации - это способ базы данных. **

(Не видел - в ответе Крагена также говорится об этом, задолго до моего)

0 голосов
/ 10 августа 2010

В обратном порядке. Лучший способ узнать, каким будет ваше выступление, - это профилировать.

Это, безусловно, вопрос "Это зависит". Лично я никогда не буду хранить такие вещи как целые числа. Во-первых, как вы упоминаете, есть коэффициент пересчета. Для другого, в какой-то момент вам или другому администратору базы данных, или кому-то придется набрать:

Select CustomerName, CustomerAddress, ContactMethods, [etc]
From Customer
Where CustomerId = xxxxx

потому что некоторые данные повреждены, или потому что кто-то ввел неправильные данные, или что-то в этом роде. ИМО требует, чтобы объединение и / или вызов функции только для того, чтобы получить основную информацию, доставляет гораздо больше хлопот, чем того стоит.

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

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