Sql表有很多列

时间:2014-12-17 08:50:06

标签: sql-server sql-server-2008 database-design architecture

我们正在为圣诞节/新年期间开发一个工作站点,个人可以基本上购买/出售他们想要的慈善机构,将其视为ebay的较小版本。

我们目前有15个父类别,这些父类别有多个具有多个子类别的子类别。

我们设计了主要项目表,包括Title,Description,CreatedBy,CreatedDate,Price等

我们现在正在进行项目属性表的设计,例如让我解释一下车辆类别,用户可以为以下各项选择一个值,里程,制造,车辆类型,门号,颜色,燃料类型,传输。

我们计划创建一个主表,其中包含每个类别的每个属性,因此它看起来像这样

PropertyId (BigInt) (PK)
ItemID (BigInt) (FK) < Links to the Main Item table
Mileage (int) (FK)
Make (int) (FK)
Type (int) (FK)
Doors (int) (FK)
Color (int) (FK)
Fuel (int) (FK)
Transmission (int) (FK)
Plus many more for each category

每列都是数据类型为int和bigint,每个FK都会链接到它所尊重的表,它会在查询时返回与int值匹配的描述,现在我没有再进一步了,我退了一步并且认为当我们开始处理所有其他类别属性时,这个表将会大幅增长,这个表可能超过150列。

我当然会创建表之间的关系,这将有助于提高性能,但我不确定这是否是正确的方法,在查询此表时我只会选择相关的字段,即车辆类别我再次只查询上面提到的字段。

但想到一张150 +柱的桌子会让我的胃转动(纯粹是因为我没有使用这么大的尺寸)这可能对DBA而言很小?我不知道,但我想我会问这里,也许会得到一些保证和指导我应该走向何方。

我做了另一方面找到了这个

Table with a lot of columns

我对Rob Nicholson以及Reed Copsey提到的内容感到厌倦,但我希望从潜在的DBA或者可能已经越过这种桥梁并提出更好方法的人那里获得更多的输入。

您的观点和意见将受到高度赞赏。

2 个答案:

答案 0 :(得分:1)

小点:为什么&#34;里程&#34;和&#34;门&#34;另一张桌子的钥匙?阿伦这些只是整数?你打算有一个&#34;门&#34;带有door_id和数字的表,以及记录(1,1),(2,2),(3,3),(4,4)等?为什么不只是存储数字并删除将数字映射到自己的表格?如果里程数将达到里程数,则需要一张包含数万条记录的表格,所有记录都将数字映射到自身。如果想法是里程数是&#34;低&#34;,&#34;中&#34;或&#34;高&#34;,而不是ok,不同的故事。

首先我会问:如果您销售许多不同类型的产品,您是否真的会处理有关每种可能产品的所有详细信息?或者您只需将所有这些转换为文本以显示在描述中吗?

也就是说,如果您销售汽车和衣服,书籍,饼干和烤面包机以及其他一千种东西,那么该程序是否会处理多少门?你会不会按门数制作报告?您是否会为用户提供一种按门数搜索汽车的方式?

如果没有,那么只需要一个名为&#34;描述&#34;的自由格式文本字段就会简单得多。并让填充数据库的人员按他们想要的方式输入。然后,您不需要为每个可能的产品类别向数据库添加字段,为每个类别的产品创建单独的数据输入屏幕,以及将所有这些单独的字段转换为格式化文本的一堆代码。如果是这种情况,那么扔掉所有未处理的字段,创建一个&#34;描述&#34;领域,你已经完成了。

如果情况并非如此,如果你真的有一个庞大的系统,每个产品类别有100个产品类别和单独的搜索屏幕 - 比如有人说他们想买车,你可以带他们去屏幕,他们可以按门数或传输类型搜索;如果有人说他们想要一本书,你可以把它们带到一个按作者或流派等搜索的屏幕上;如果有人想要一台烤面包机,他们会去一个屏幕,在那里他们可以搜索切片的数量,电子与电子的对比;如果有人想要衣服,那么他们可以根据尺寸,材料,颜色等进行搜索;对于你能想到的每种不同类型的产品......等等......我说你正在构建一个巨大的系统。但没关系。

基本上有三种方法可以做到这一点:

  1. 每个产品记录都有一个类型代码。某些字段与某些类型相关,而与其他字段无关。不相关的字段保留为空。是的,一张桌子中的150个字段很多。我创建的大多数表可能有十几个字段。当然没有最大数量,但如果你超过30,我就会开始质疑它。管理变得非常困难。我已经创建了一些表格,其中一些字段与某些记录类型无关,但是有一些字段非常明显。由于你的所有字段都是短标识符,我怀疑这会损害性能:150个整数点,每个可能是4个字节,600个字节,一些开销,因数据库引擎而异,但你仍然在谈论数百个字节,而不是对大多数数据库引擎来说负担过重。更大的问题是程序员要跟踪这一切。

  2. 使用所有产品通用的信息创建产品记录,可能包括ID,类型,描述,价格等等。然后使用每种类型的详细信息创建子类型表。因此,对于每辆车都有产品记录和产品车记录,每个烤面包机都有产品记录和产品 - 烤面包机记录等。子类型记录包含指向产品记录的指针,以及当你展示时,你必须找到并阅读两者。

  3. 创建产品表和产品属性表。 product-attribute表包含属性的名称,例如&#34; color&#34;,以及值,例如&#34; blue&#34;。然后,您可以为任何产品提供任何属性集。这很糟糕,我强烈建议不要这样做。管理是不可能的。你如何控制属性的名称?如果用户只是在数据输入时输入属性名称和值,那么整个地方就会出现不一致的情况,就像一个人放置&#34;品牌&#34;另一个是制造商&#34;,一个放置&#34;门&#34;还有另外一些&#34;门数&#34;等等。

  4. 略好于3,创建一个属性表,列出所有使用某种id的属性的名称。创建producttype-attribute表,列出哪些属性与哪种产品类型相关。创建一个产品属性表,该表提供给定产品的属性值。与产品(id,类型,描述,价格),属性(id,name),producttype-attribute(type,attribute_id),product-attribute(product_id,attribute_id)类似。在代码中使用producttype-attribute表来确定在数据输入时以及为客户显示时,在任何给定产品类型的屏幕上显示哪些属性。这比3更好,因为它可以使事情保持一致和受控制。

答案 1 :(得分:1)

我强烈建议您以这种方式进行设置。 INT是一个固定长度的字段 - 这意味着您将占用大量空值的数据库空间。而是为您拥有的每个类别创建不同的“项属性”表。您仍将拥有相同数量的字段,但它们将分布在不同的表中。使用起来更容易,查询效率更高。

如果你真的觉得你需要一个Item Properties表,我会把它变成抽象而忘记外键。您需要一种不同的方式来强制引用完整性,但从长远来看它会表现得更好。例如,而不是:

CREATE TABLE ItemProperties
    (
      id BIGINT IDENTITY(1, 1) ,
      itemId BIGINT ,
      mileage INT , --auto
      make INT , --auto
      mpg INT , --auto
      length INT , --boat
      motorhp INT , --boat
      motormake INT --boat
    )

这样做:

CREATE TABLE ItemProperties
    (
      id BIGINT IDENTITY(1, 1) ,
      itemId BIGINT ,
      property1 INT ,
      property2 INT ,
      property3 INT
    )

CREATE TABLE PropertyDefinition
    (
      id BIGINT IDENTITY(1, 1) ,
      itemId INT ,
      property1label VARCHAR(255) ,
      property2label VARCHAR(255) ,
      property3label VARCHAR(255)
    )

    INSERT INTO dbo.PropertyDefinition
            ( itemId ,
              property1label ,
              property2label ,
              property3label
            )
    VALUES  ( 1 , -- auto
              'mileage' , 
              'make' , 
              'restofautoproperties'  
            ),
            ( 2, --boat
            ,'length',
            'motorhp',
            'motormake'
            )