Как предотвратить создание статистики по столбцу?

18

У меня есть таблица со столбцом, для которого я не хочу, чтобы статистика создавалась или обновлялась. Я получу лучшую оценку количества соединений, если заставлю оптимизатор запросов использовать плотность статистики по первичному ключу, а не гистограмму статистики по этому столбцу. Автоматическое обновление и автоматическое создание статистики включены на уровне базы данных, и я не могу это изменить.

Если вы хотите предложить альтернативы предотвращению создания статистики, имейте в виду, что таблица используется в представлении, на которое ссылаются тысячи различных запросов. У меня нет контроля над запросами, которые выполняются.

Моя первоначальная стратегия заключалась в создании статистики на колонке с NOCOMPUTEи SAMPLE 0 ROWSопциями. У меня сложилось впечатление, что SQL Server не будет автоматически создавать статистику для столбца, в котором уже есть объект статистики, но это произошло на наших серверах dev и QA.

Новая статистика была создана для COL_GROUP. Моя NORECOMPUTEстатистика не была обновлена. Я не знаю, почему была создана статистика, и я сам не смог ее запустить, выполнив запросы.

Есть ли способ запретить SQL Server автоматически создавать статистику по одному столбцу? Моя таблица имеет только два столбца, поэтому решение, предотвращающее создание автостатики для одной таблицы, также решило бы мою проблему.

Флаги трассировки 4139 и 2371 включены, если это имеет значение.

Если вы хотите поэкспериментировать со структурой таблицы, я включил ее и примеры данных ниже:

CREATE TABLE X_NO_COLUMN_STATS(
    [COL_USER] [varchar](256) NOT NULL,
    [COL_GROUP] [int] NOT NULL,
 CONSTRAINT [PK_X_NO_COLUMN_STATS] PRIMARY KEY CLUSTERED 
(
    [COL_USER] ASC,
    [COL_GROUP] ASC
)WITH (DATA_COMPRESSION = PAGE)
);

-- prevent stats from being updated on COL_GROUP
CREATE STATISTICS [X_NO_COLUMN_STATS__COL_GROUP] ON X_NO_COLUMN_STATS ([COL_GROUP]) WITH NORECOMPUTE, SAMPLE 0 ROWS;

BEGIN TRANSACTION;
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',104);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',106);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',107);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',108);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',110);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',111);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',112);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',113);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',114);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',116);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',117);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',118);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',121);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',123);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',124);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',125);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',126);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',129);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',132);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',137);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',139);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',140);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',144);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',145);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',147);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',152);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',153);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',154);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',155);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',162);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',163);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',165);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',168);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',169);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',170);
INSERT INTO X_NO_COLUMN_STATS VALUES ('CUSER1',178);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',102);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',103);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',109);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',110);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',111);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',112);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',114);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',115);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',119);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',120);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',121);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',123);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',124);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',126);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',128);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',136);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',137);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',138);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',142);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',143);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',148);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',151);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',152);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',155);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',156);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',157);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',158);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',165);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',167);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',168);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',169);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',171);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',173);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',176);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',177);
INSERT INTO X_NO_COLUMN_STATS VALUES ('OUSER19',178);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',104);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',108);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',109);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',111);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',112);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',113);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',114);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',116);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',117);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',118);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',121);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',123);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',124);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',125);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',126);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',129);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',132);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',137);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',139);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',140);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',144);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',145);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',147);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',152);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',154);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',155);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',162);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',163);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',165);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',168);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',169);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',170);
INSERT INTO X_NO_COLUMN_STATS VALUES ('TUSER30',178);
COMMIT TRANSACTION;

Я знаю, sp_autostatsно мне нужно что-то, чтобы предотвратить создание автоматической статистики. sp_autostatsтолько предотвращает автоматическое обновление статистики.

Джо Оббиш
источник
1
Сколько данных содержит ваша фактическая таблица? А сколько данных добавляется ежедневно?
Джон aka hot2use
Вы смотрели на создание статистики по обоим столбцам и видели, как это влияет на производительность запроса? CREATE STATISTICS [X_NO_COLUMN_STATS__COL_GROUP] ON X_NO_COLUMN_STATS ([COL_USER], [COL_GROUP]); Если оба столбца находятся в предложении where, они не будут создавать статистику для COL_GROUP, но если это будет только COL_GROUP, это будет сделано. Но в этом случае производительность должна быть лучше с этой статистикой, чем статистика COL_USER.
cfradenburg

Ответы:

1

Создайте новую базу данных (назовем ее TestStats), отключите автоматическое создание статистики и переместите туда таблицу X_NO_COLUMN_STATS. После этого создайте представление в вашей базе данных, которое будет указывать на таблицу без гистограммы:

CREATE VIEW X_NO_COLUMN_STATS
AS
    SELECT [COL_USER], [COL_GROUP] FROM TestStats.dbo.X_NO_COLUMN_STATS;
GO

Если я правильно понял вашу проблему, вы достигнете того, чего хотите. Ваши операции CRUD будут работать с таблицей без статистики (да, она будет расположена в другой базе данных, и об этом следует всегда помнить) через представление с тем же именем, что и ваша таблица.

Денис Резник
источник
К сожалению, у этого есть много недостатков: он разрывает отношения с внешним ключом, вводит транзакции между базами данных, делает резервное копирование и восстановление в определенный момент времени более сложным и т. Д.
Брент Озар
@BrentOzar точно! Но это часто случается для сложных задач - решая, что будет хуже прямо здесь :)
Денис Резник