用数据表中的 ID 替换名称的快速方法?
Fast Way to Replace Names with Ids in Datatable?
我有一个非常大的 CSV 文件,我必须定期加载它,其中包含时间序列数据。 headers 的示例如下:
| SiteName | Company | Date | ResponseTime | Clicks |
此数据来自上传者外部的服务。 SiteName
和 Company
都是字符串字段。在数据库中,这些是标准化的。有一个Site
table和一个Company
table:
CREATE TABLE [dbo].[Site] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[Name] NVARCHAR(MAX) NOT NULL
)
CREATE TABLE [dbo].[Company] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[Name] NVARCHAR(MAX) NOT NULL
)
还有数据table。
CREATE TABLE [dbo].[SiteStatistics] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[CompanyId] INT NOT NULL,
[SiteId] INT NOT NULL,
[DataTime] DATETIME NOT NULL,
CONSTRAINT [SiteStatisticsToSite_FK] FOREIGN KEY ([SiteId]) REFERENCES [Site]([Id]),
CONSTRAINT [SiteStatisticsToCompany_FK] FOREIGN KEY ([CompanyId]) REFERENCES [Company]([Id])
)
CSV 文件中大约有 200 万行,任何类型的 IO-bound 迭代都不起作用。我需要在几分钟内完成,而不是几天。
我最初的想法是我可以 pre-load Site
和 Company
到数据表中。我已经将 CSV 以与 CSV 列匹配的格式加载到数据 table 中。我现在需要用 Site
的 Id 字段替换每个 SiteName
,用 Company
的 Id 字段替换每个 Company
。处理此问题最快、最有效的方法是什么?
如果您使用预加载网站和公司,您可以使用代码获得不同的值:
DataView view = new DataView(table);
DataTable distinctCompanyValues = view.ToTable(true, "Company")
DataView view = new DataView(table);
DataTable distinctSiteValues = view.ToTable(true, "Site")
然后使用 Sql-Bulk-Copy 将这两个数据表加载到它们的 SQL 表中。
接下来将所有数据转储到:
CREATE TABLE [dbo].[SiteStatistics] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[CompanyId] INT DEFAULT 0,
[SiteId] INT DEFAULT 0,
[Company] NVARCHAR(MAX) NOT NULL,
[Site] NVARCHAR(MAX) NOT NULL,
[DataTime] DATETIME NOT NULL
)
然后执行更新以设置参照完整性字段:
UPDATE [SiteStatistics] ss SET
[CompanyId] = (SELECT Id FROM [Company] c Where ss.[Company] = c.Name),
[SiteId] = (SELECT Id FROM [Site] s Where ss.[Site] = s.Name)
添加外键约束:
ALTER TABLE [SiteStatistics] ADD CONSTRAINT [SiteStatisticsToSite_FK] FOREIGN KEY ([SiteId]) REFERENCES [Site]([Id])
ALTER TABLE [SiteStatistics] ADD CONSTRAINT [SiteStatisticsToCompany_FK] FOREIGN KEY ([CompanyId]) REFERENCES [Company]([Id])
最后从 SiteStatistics 中删除站点和公司名称字段:
ALTER TABLE [SiteStatistics] DROP COLUMN [Company];
ALTER TABLE [SiteStatistics] DROP COLUMN [Site];
我有一个非常大的 CSV 文件,我必须定期加载它,其中包含时间序列数据。 headers 的示例如下:
| SiteName | Company | Date | ResponseTime | Clicks |
此数据来自上传者外部的服务。 SiteName
和 Company
都是字符串字段。在数据库中,这些是标准化的。有一个Site
table和一个Company
table:
CREATE TABLE [dbo].[Site] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[Name] NVARCHAR(MAX) NOT NULL
)
CREATE TABLE [dbo].[Company] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[Name] NVARCHAR(MAX) NOT NULL
)
还有数据table。
CREATE TABLE [dbo].[SiteStatistics] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[CompanyId] INT NOT NULL,
[SiteId] INT NOT NULL,
[DataTime] DATETIME NOT NULL,
CONSTRAINT [SiteStatisticsToSite_FK] FOREIGN KEY ([SiteId]) REFERENCES [Site]([Id]),
CONSTRAINT [SiteStatisticsToCompany_FK] FOREIGN KEY ([CompanyId]) REFERENCES [Company]([Id])
)
CSV 文件中大约有 200 万行,任何类型的 IO-bound 迭代都不起作用。我需要在几分钟内完成,而不是几天。
我最初的想法是我可以 pre-load Site
和 Company
到数据表中。我已经将 CSV 以与 CSV 列匹配的格式加载到数据 table 中。我现在需要用 Site
的 Id 字段替换每个 SiteName
,用 Company
的 Id 字段替换每个 Company
。处理此问题最快、最有效的方法是什么?
如果您使用预加载网站和公司,您可以使用代码获得不同的值:
DataView view = new DataView(table);
DataTable distinctCompanyValues = view.ToTable(true, "Company")
DataView view = new DataView(table);
DataTable distinctSiteValues = view.ToTable(true, "Site")
然后使用 Sql-Bulk-Copy 将这两个数据表加载到它们的 SQL 表中。
接下来将所有数据转储到:
CREATE TABLE [dbo].[SiteStatistics] (
[Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[CompanyId] INT DEFAULT 0,
[SiteId] INT DEFAULT 0,
[Company] NVARCHAR(MAX) NOT NULL,
[Site] NVARCHAR(MAX) NOT NULL,
[DataTime] DATETIME NOT NULL
)
然后执行更新以设置参照完整性字段:
UPDATE [SiteStatistics] ss SET
[CompanyId] = (SELECT Id FROM [Company] c Where ss.[Company] = c.Name),
[SiteId] = (SELECT Id FROM [Site] s Where ss.[Site] = s.Name)
添加外键约束:
ALTER TABLE [SiteStatistics] ADD CONSTRAINT [SiteStatisticsToSite_FK] FOREIGN KEY ([SiteId]) REFERENCES [Site]([Id])
ALTER TABLE [SiteStatistics] ADD CONSTRAINT [SiteStatisticsToCompany_FK] FOREIGN KEY ([CompanyId]) REFERENCES [Company]([Id])
最后从 SiteStatistics 中删除站点和公司名称字段:
ALTER TABLE [SiteStatistics] DROP COLUMN [Company];
ALTER TABLE [SiteStatistics] DROP COLUMN [Site];