我该如何确保mytable高效

时间:2010-07-18 16:56:04

标签: sql sql-server tsql sql-server-2000

我正在设计一个可能有200K行的新表。 我想确保对此表的查询是有效的。

在过去,我总是给出一行唯一的id,假设这会产生一个索引:

CREATE TABLE [dbo].[Equipment](
    [EquipID] [nchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [EquipDescription] [nchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Category] [nchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [id] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]

这够了吗? ,我应该设置一个主键。

如果有人有建议,请让他们飞。

T-SQL,SQL2000,

5 个答案:

答案 0 :(得分:3)

如果您创建主键或显式创建主键,则只能获得索引。您需要的索引由您的查询决定,只是在列上有索引不会使查询更快,除非您查询或加入该列。

指数也不是没有成本,它们会使您的数据库变大,并且会增加修改表格的成本。

这个article虽然陈旧,但似乎很好地概述了指数。

如果您打算使用数据库获取像Database Systems这样的数据库教科书并阅读它,那将证明无价之宝。找到最有效的索引和查询排列很困难,而试错也不是尝试优化查询的好方法。

答案 1 :(得分:1)

最佳做法是在表格上创建主键。正如@deinst指出的那样,除非您明确创建索引,否则不会获得索引。创建主键是创建索引的一种方法。

[id]列可能是主键的一个很好的候选者。并且,将它作为您的聚簇索引(每个表获得一个聚簇索引)可能是可以的,这是创建主键时的默认值。

您可能希望根据查询表的方式在其他列上创建索引(再次由@deinst指示)。

[EquipID]是表格的自然键。自然键是业务域中的唯一属性。业务人员如何参考每个项目。如果[EquipID]是自然键,您可能希望为此列添加唯一约束或唯一索引,并且您可能希望将其可为空性更改为NOT NULL。

答案 2 :(得分:1)

数据库优化本身就是一门艺术/科学,数据建模也是如此。首先确保您的架构是可靠的并支持您的应用程序。然后,您可以添加索引以提高查询性能。但是,不要根据一些概念做出数据建模选择,即选择会以某种方式使表更快地查询。

1)除了性能之外,所有表都应该有一个主键。您需要能够唯一地识别记录。

2)查询的性能和哪些索引将提高效率取决于查询。如果您在JOIN,WHERE子句或ORDER BY子句中使用列,那么它应该有一个索引。您的主键将自动获取索引,因此请考虑以这种方式使用哪些其他列。在某些情况下,多列索引是最佳选择。

答案 3 :(得分:0)

你应该问自己的第一件事是“'装备'的属性是什么?”一台设备是否可以没有EquipID,描述或类别?如果不是,则不应允许这些列为空。

其次是“唯一定义一件'装备'的东西?”它是EquipID吗?那应该是你的主键。它是EquipID和Category的组合吗?然后,您有一个由两列组成的复合主键。但是,有时候,数据自然不适合在完全关系模型中可以轻松加入的主键。因此,您可以像显示的那样考虑身份ID列 - 这称为代理键。知道默认情况下创建主键会在这些键列上创建聚簇索引。如果你采用代理键方法,那么恕我直言,最好为你的对象的唯一性创建另一个独特的索引(即EquipID)。

就其他索引而言,你应该进一步问自己“我最常要查询哪些列?”也许你会有很多问题,比如“SELECT EquipID FROM Equipment WHERE Category = 3”。这表明Category是索引的一个很好的候选列。

最后,另一个好的经验法则是索引任何外键列 - 它似乎是Category。这会优化您可能执行的任何连接查询。

对此的一个好方法是下面的内容(快速抛出,未经测试):

CREATE TABLE [dbo].[Equipment]( 
  [EquipID] [nchar](20) NOT NULL
  ,[EquipDescription] [nchar](100) NOT NULL
  ,[CategoryID] [bigint] NOT NULL
  ,CONSTRAINT [PK_Equipment] PRIMARY KEY CLUSTERED (
    [EquipID] ASC
  )
) ON [PRIMARY] 
GO

CREATE TABLE [dbo].[Categories]( 
  [CategoryID] [bigint] IDENTITY(1,1) NOT NULL 
  ,[CategoryName] [nchar](100) NOT NULL
  ,CONSTRAINT [PK_Categories] PRIMARY KEY CLUSTERED (
    [CategoryID] ASC
  )
) ON [PRIMARY] 
GO

CREATE NONCLUSTERED INDEX [IDX_Equipment_Category] ON [dbo].[Equipment] (
  [CategoryID] ASC
) ON [PRIMARY]

CREATE UNIQUE NONCLUSTERED INDEX [IDX_Categories_CategoryName] ON [dbo].[Categories] (
  [CategoryName] ASC
) ON [PRIMARY]

ALTER TABLE [dbo].[Equipment]  WITH CHECK ADD  CONSTRAINT [FK_Equipment_Categories] 
FOREIGN KEY([CategoryID]) REFERENCES [dbo].[Categories] ([CategoryID])
GO

答案 4 :(得分:0)

如果不发布您将拥有的查询关系,这个问题是无法回答的。

  • 您是否要始终通过id引用设备?或者EquipID
  • 其他表是否通过存储id值或EquipID来存储引用(外键)?
  • 您打算按Category汇总吗?
  • Category隐含的层次结构是什么?
  • 设备的EquipID是否有变化?