TSQL INFORMATION_SCHEMA.COLUMNS VS sys.columns VS COL_LENGTH('Table','ColumnName')

TSQL INFORMATION_SCHEMA.COLUMNS VS sys.columns VS COL_LENGTH('Table','ColumnName')

我发现了这几个变体来检查列是否存在。一些评论说访问 INFORMATION_SCHEMA 视图或 sys.columns 访问磁盘,而 COL_LENGTH 使用缓存数据库,但我真的不明白这是什么意思。

我找不到任何解释架构如何存储在磁盘上、如何缓存以及这 3 个选项之间的性能差异的内容。

谁能给我解释一下?

SQL 服务器存储有关您的数据库及其内容的元数据。这些通常通过 sys. table 和 information_schema. 视图访问。

系统 tables 在某种程度上特定于 SQL 服务器,并且趋向于相当规范化。相比之下,information_schema 视图(与您可能创建的其他许多报告视图一样)以更易读的格式提供数据 - 它们通常将各种系统 table 连接在一起以获得结果。有关详细信息,请参阅 Difference between Information_schema vs sys tables in SQL Server

COL_LENGTH() 是一个对数据库进行操作的函数,不需要 'read data' 这样的。

但是,出于所有实际目的,您会发现它们之间的差异为零。如果您只是在特定列的列长度之后,请使用 COL_LENGTH,因为它可能会稍微快一些。否则请随意使用 information_schema 视图,因为它们提供了更多 easy-to-read 信息(或一组自定义的 sys tables 连接在一起),因为获取元数据的读取次数非常少.

例如,我有一个用于测试的 table,名为 'test',有 5 列(ID、col2、col3、col4、col5)。它有将近 200 万行,但 table 中的 none 数据实际上需要读取 - 只是元数据。

我 运行 从每个命令中获取列 lengths/info 的命令。每个都需要 0.000 秒才能完成(例如,不到 1 毫秒)。以下是用于展示部分差异的命令和结果(仅前 10 列)。

SELECT col_length('dbo.test', 'col2') AS Col2_info
  /*
  Col2_info
  100
  */

SELECT * FROM sys.columns where object_id = (SELECT TOP 1 object_id FROM sys.objects WHERE name = 'test')
  /*
  object_id   name  column_id  system_type_id  user_type_id  max_length  precision  scale  collation_name        is_nullable  is_ansi_padded
  2094630505  ID    1          56              56            4           10         0      NULL                  0            0
  2094630505  col2  2          167             167           100         0          0      Latin1_General_CI_AS  0            1
  2094630505  col3  3          167             167           100         0          0      Latin1_General_CI_AS  1            1
  2094630505  col4  4          167             167           100         0          0      Latin1_General_CI_AS  1            1
  2094630505  col5  5          167             167           100         0          0      Latin1_General_CI_AS  1            1
  */

SELECT * from information_schema.COLUMNS where table_name = 'test'
  /*
  TABLE_CATALOG  TABLE_SCHEMA  TABLE_NAME  COLUMN_NAME  ORDINAL_POSITION  COLUMN_DEFAULT  IS_NULLABLE  DATA_TYPE  CHARACTER_MAXIMUM_LENGTH
  Testdb         dbo           test        ID           1                 NULL            NO           int        NULL
  Testdb         dbo           test        col2         2                 NULL            NO           varchar    100
  Testdb         dbo           test        col3         3                 NULL            YES          varchar    100
  Testdb         dbo           test        col4         4                 NULL            YES          varchar    100
  Testdb         dbo           test        col5         5                 NULL            YES          varchar    100
  */

请注意,在上面的版本中,sys.columns 版本 a) 更难构造,因为它只与我的 test_table 的 object_id 相关;它还提供比 information_schema 版本更难阅读的数据。