Общее решение - это разбить вашу таблицу на две или более таблиц, т.е. нормализовать структуру данных. Я думаю, что можно ввести еще две таблицы - для кампаний и тем
НО
Для ваших существующих структур данных вы можете создать вычисляемый столбец uniqueidentifier
или bigint
в виде хеша поля TopicName
, проиндексировать его и искать хеш вместо строкового поля. Я приведу вам пример с bigint
:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[HashString64SVF](@input NVARCHAR(4000))
RETURNS BIGINT
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS
BEGIN
RETURN
CAST(SUBSTRING(HASHBYTES('SHA1', UPPER(@Input)), 1, 8) AS BIGINT)
^ CAST(SUBSTRING(HASHBYTES('SHA1', UPPER(@Input)), 9, 8) AS BIGINT)
^ CAST(SUBSTRING(HASHBYTES('SHA1', UPPER(@Input)), 17, 4) AS BIGINT)
END
GO
ALTER TABLE datatable ADD TopicNameHash AS dbo.HashString64SVF(TopicName)
GO
CREATE INDEX NewIndexName ON DataTable(TopicNameHash, CampaignID, Category) INCLUDE(PostId)
GO
UPDATE datatable
SET TopicFrequency = b.TopicFrequency
FROM datatable
JOIN
(SELECT CampaignID, Category, TopicNameHash, COUNT(DISTINCT PostID) AS TopicFrequency
FROM datatable GROUP BY CampaignID, Category, TopicNameHash) AS b
ON datatable.CampaignID = b.CampaignID
AND datatable.Category = b.Category
AND datatable.TopicNameHash = b.TopicNameHash
И
Создание первичного ключа в столбце RowId
И
Воссоздайте таблицу следующим образом:
CREATE TABLE [datatable](
[RowID] [int] IDENTITY(1,1) PRIMARY KEY,
[CampaignID] [int] NOT NULL,
[Category] [nvarchar](255) NOT NULL,
[PostID] [int] NOT NULL,
--uncomment if needed [TopicNameHash] AS dbo.HashString64SVF(TopicName),
[TopicFrequency] [int] NULL,
[CampaignName] [nvarchar](255) NULL,
[TopicName] [nvarchar](4000) NULL
)
Основная причина - если столбцы переменных с пустыми значениями находятся в конце списка столбцов и в этих столбцах много значений NULL
- сервер sql может сэкономить немного места в строке и, следовательно, - в IO