จะป้องกันการสร้างสถิติในคอลัมน์ได้อย่างไร?


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
ตารางจริงของคุณมีข้อมูลเท่าใด และมีการเพิ่มข้อมูลในแต่ละวันเป็นจำนวนเท่าใด
John aka hot2use

คุณเคยดูการสร้างสถิติทั้งสองคอลัมน์แล้วดูว่ามันมีผลต่อประสิทธิภาพของการสืบค้นอย่างไร สร้างสถิติ [X_NO_COLUMN_STATS__COL_GROUP] เมื่อ X_NO_COLUMN_STATS ([COL_USER], [COL_GROUP]); หากทั้งสองคอลัมน์อยู่ในตำแหน่งที่มันจะไม่สร้างสถิติใน 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 ของคุณจะทำงานกับตารางที่ไม่มีสถิติ (ใช่มันจะอยู่ในฐานข้อมูลอื่นและควรจำไว้เสมอ) ผ่านมุมมองที่มีชื่อเดียวกับตารางของคุณ


แต่น่าเสียดายที่นี้มีจำนวนมากข้อเสีย: มันแบ่งความสัมพันธ์ที่สำคัญต่างประเทศแนะนำการทำธุรกรรมข้ามฐานข้อมูลทำให้การกู้คืนและสำรองข้อมูลที่จะเป็นจุดเดียวในเวลาที่ท้าทายมากขึ้น ฯลฯ
Brent Ozar

@BrentOzar แน่นอน! แต่มันเกิดขึ้นค่อนข้างบ่อยสำหรับงานที่ท้าทาย - การตัดสินใจว่าจะเลวร้ายยิ่งขวาที่นี่ :)
เดนิส Reznik
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.