ปรับการค้นหาให้เหมาะสมสำหรับ 25+ ล้านแถว


11

ฉันใช้ MS SQL และฉันต้องเรียกใช้แบบสอบถามหลายรายการในตารางเดียวกันในเกณฑ์ที่แตกต่างกัน ตอนแรกฉันเรียกใช้แบบสอบถามแต่ละรายการในตารางเดิมแม้ว่าพวกเขาทั้งหมดแชร์การกรองบางอย่าง (เช่นวันที่สถานะ) การดำเนินการนี้ใช้เวลานาน (ประมาณ 2 นาที)

มีข้อมูลที่ซ้ำกันในแถวข้อมูลและดัชนีทั้งหมดไม่ได้เป็นคลัสเตอร์ ฉันสนใจเฉพาะคอลัมน์ 4 คอลัมน์สำหรับเกณฑ์ของฉันและผลลัพธ์ควรให้ผลลัพธ์การนับเท่านั้นสำหรับการค้นหาทั้งหมด

คอลัมน์ที่ต้องการ: TABLE, FIELD, AFTER, DATEและมีดัชนีในแต่ละและDATETABLE

หลังจากสร้างตารางชั่วคราวที่มีเฉพาะฟิลด์ที่ฉันต้องการมันลงไปเป็นเวลา 1:40 นาทีซึ่งยังแย่มาก

CREATE TABLE #TEMP
(
    TABLE VARCHAR(30) NULL,
    FIELD VARCHAR(30) NULL,
    AFTER VARCHAR(1000) NULL,
    DATE DATETIME,
    SORT_ID INT IDENTITY(1,1)
)
CREATE CLUSTERED INDEX IX_ADT ON #TEMP(SORT_ID)

INSERT INTO #TEMP (TABLE, FIELD, AFTER, DATE)
    SELECT TABLE, FIELD, AFTER, DATE 
    FROM mytbl WITH (NOLOCK)
    WHERE TABLE = 'OTB' AND
    FIELD = 'STATUS'

เรียกใช้สิ่งนี้ -> (216598 แถวที่ได้รับผลกระทบ)

เนื่องจากข้อความค้นหาทั้งหมดไม่ขึ้นอยู่กับช่วงวันที่ฉันจึงไม่รวมอยู่ในแบบสอบถาม ปัญหาก็คือว่ามันพากันดังกล่าวข้างต้น 1 นาทีเพื่อแทรกเท่านั้น เม็ดมีดด้านบนใช้เวลา1:19 นาที

ฉันต้องการเรียกใช้บางสิ่งเช่นนี้สำหรับข้อความค้นหาหลายรายการ

SELECT COUNT(*) AS COUNT
FROM #TEMP
WHERE AFTER = 'R' AND
DATE >= '2014-01-01' AND
DATE <= '2015-01-01'

มันเป็นปัญหาของการแทรกมากกว่าที่เลือก แต่อุณหภูมิมีวิธีแถวน้อยกว่าตารางเดิมซึ่งอาจจะดีกว่าที่จะผ่านตารางหลาย ๆ ครั้ง

ฉันจะเพิ่มประสิทธิภาพสิ่งนี้ได้อย่างไร

แก้ไข

ฉันได้ลบรหัสการเรียงลำดับแล้วฉันคิดว่าปัญหาส่วนใหญ่เป็นการเลือกและไม่แทรก มันเป็นการเดา

ฉันไม่สามารถสร้างเอกลักษณ์ในดัชนีใด ๆ เนื่องจากไม่มีเขตข้อมูลหรือแถวที่ไม่ซ้ำกัน

ฉันใช้ SQL Server 2012

ข้อมูลตาราง : มันเป็นกองและมีการใช้พื้นที่ดังต่อไปนี้:

name    rows        reserved    data        index_size  unused
mytbl   24869658    9204568 KB  3017952 KB  5816232 KB  370384 KB

@MikaelEriksson ฉันไม่สามารถปรับเปลี่ยนตารางการผลิตได้ ..
Atieh

หากแบบสอบถามที่คุณพยายามปรับให้เหมาะสมนั้นอยู่ในรูปแบบSELECT COUNT(*) AS COUNT FROM original_table WHERE AFTER = 'R' AND DATE >= '2014-01-01' AND DATE < '2015-01-01'ทำไมคุณไม่ลองปรับแต่ละข้อ (แบบสอบถาม) แยกต่างหาก คุณไม่ได้รับอนุญาตให้เพิ่มดัชนีในตารางหรือไม่?
ypercubeᵀᴹ

2
คุณต้องระบุสาเหตุที่ช้า มันถูกบล็อกหรือไม่ มันกำลังรอให้ tempdb เติบโตหรือไม่ แผนการดำเนินการเป็นสุดซึ้งหรือไม่ ไม่มีใครสามารถแก้ไข "แบบสอบถามของฉันคือช้า" โดยไม่มีรายละเอียดเพิ่มเติม ...
แอรอนเบอร์ทรานด์

3
ดูเหมือนว่าจะเป็นสาเหตุที่ทำให้ฉันหลงทาง ( "ฉันไม่ได้รับอนุญาตให้เพิ่มประสิทธิภาพอะไรเลยดังนั้นเพียงแค่กด 200K แถวในตารางชั่วคราวทุกครั้งที่เราต้องการเรียกใช้แบบสอบถาม" ) แต่คุณสามารถลบTABLEและFIELDคอลัมน์จาก#tempตาราง (แถวทั้งหมดมีTABLE = 'OTB' AND FIELD = 'STATUS'ไว้สำหรับตารางอุณหภูมิเฉพาะหลังจากทั้งหมด)
ypercubeᵀᴹ

2
ฉันขอแก้ไขและปรับปรุงโดยเพิ่มความคิดเห็น (และสุภาพ) อย่างละเอียด นั่นคือสิ่งที่แสดงความคิดเห็น คุณควรติดแท็กคำถามของคุณด้วยรุ่นของ SQL Server ที่คุณกำลังใช้ (เช่น SQL Server 2014) DDL สำหรับตารางอาจมีประโยชน์เช่นกัน ( CREATE TABLEคำสั่ง) การลงคะแนนเสียงเป็นเพราะคำถามไม่ชัดเจน
พอลไวท์ 9

คำตอบ:


12

คำถามส่วนใหญ่เกี่ยวกับวิธีเพิ่มประสิทธิภาพคำสั่ง select:

SELECT [TABLE], [FIELD], [AFTER], [DATE]
FROM mytbl WITH (NOLOCK)
WHERE [TABLE] = 'OTB' AND
[FIELD] = 'STATUS'

การลบโปรเจ็กต์ที่ซ้ำซ้อนและเพิ่มdboสคีมาที่สันนิษฐานไว้:

SELECT [AFTER], [DATE] 
FROM dbo.mytbl WITH (NOLOCK)
WHERE [TABLE] = 'OTB'
AND FIELD = 'STATUS';

ไม่มีดัชนีเช่น([TABLE],[FIELD]) INCLUDE ([AFTER],[DATE])SQL Server มีสองตัวเลือกหลัก:

  1. สแกนฮีปทั้งหมด (3GB +); หรือ
  2. ค้นหาการจับคู่แถว[TABLE] = 'OTB'และ[FIELD] = 'STATUS'(โดยใช้IDX6) จากนั้นทำการค้นหาฮีป (RID) ต่อแถวเพื่อดึงข้อมูลคอลัมน์[AFTER]และ[DATE]

เครื่องมือเพิ่มประสิทธิภาพเลือกการสแกนฮีปหรือการค้นหาดัชนีด้วยการค้นหา RID หรือไม่ขึ้นอยู่กับการเลือกโดยประมาณของ[TABLE] = 'OTB'และเพ[FIELD] = 'STATUS'รดิเคต ตรวจสอบดูว่าจำนวนแถวโดยประมาณจากการค้นหาตรงกับความเป็นจริง หากไม่อัปเดตสถิติของคุณ ทดสอบแบบสอบถามที่มีคำใบ้ตารางบังคับใช้ดัชนีถ้าเงื่อนไขที่เป็นเลือกพอสมควร หากเพิ่มประสิทธิภาพในขณะนี้คือการเลือกดัชนีแสวงหาทดสอบประสิทธิภาพด้วยการINDEX(0)หรือFORCESCANคำแนะนำในการสแกนกอง

นอกจากนั้นคุณสามารถปรับปรุงการสแกนของกองได้เพียงเล็กน้อยโดยลบพื้นที่ที่ไม่ได้ใช้บางส่วน (370MB) ใน SQL Server 2008 สามารถทำได้โดยการสร้างฮีปขึ้นใหม่ พื้นที่ที่ไม่ได้ใช้ในฮีปมักเป็นผลมาจากการลบที่ดำเนินการโดยไม่มีการล็อคตาราง (โดยไม่มีการล็อคตารางหน้าว่างจะไม่ถูกจัดสรรคืนจากฮีป) ตารางที่พบว่ามีการลบบ่อยครั้งมักถูกเก็บไว้เป็นตารางคลัสเตอร์ได้ดีขึ้นด้วยเหตุนี้

ประสิทธิภาพของการสแกนฮีปขึ้นอยู่กับจำนวนของตารางที่จัดเก็บในหน่วยความจำต้องอ่านจากดิสก์จำนวนหน้าเต็มความเร็วของการจัดเก็บแบบต่อเนื่องไม่ว่าจะเป็นการสแกน I / O หรือ CPU ที่ถูกผูกไว้ ( ความเท่าเทียมสามารถช่วยได้)

หากประสิทธิภาพยังไม่เป็นที่ยอมรับหลังจากที่คุณตรวจสอบทุกข้อข้างต้นแล้วให้ลองสร้างดัชนีใหม่ หากมีอยู่ใน SQL Server เวอร์ชันของคุณดัชนีที่กรองได้สำหรับแบบสอบถามที่ระบุจะเป็นดังนี้:

CREATE INDEX index_name
ON dbo.mytbl ([DATE],[AFTER])
WHERE [TABLE] = 'OTB'
AND [FIELD] = 'STATUS';

พิจารณาการบีบอัดดัชนีด้วยถ้ามีและเป็นประโยชน์ หากไม่มีดัชนีใหม่บางชนิดคุณสามารถทำได้เล็กน้อยเพื่อปรับปรุงประสิทธิภาพของการสืบค้นที่กำหนด


IDX6 nonclustered located on PRIMARY TABLE, FIELDขออภัยพอลมี: อาจจะเปลี่ยนสิ่งที่คุณพูดถึง?
Atieh

6

ฉันคิดว่ามีกรณีสำหรับการเปลี่ยนดัชนีที่นี่เพราะ:

  • คุณมีงานที่ต้องทำ (แบบสอบถามจำนวนมากเหล่านี้)
  • ปริมาณคลังข้อมูล (25+ ล้านแถว) และ
  • ปัญหาด้านประสิทธิภาพ

นี่จะเป็นกรณีการใช้งานที่ดีสำหรับดัชนี columnstore ที่ไม่ใช่คลัสเตอร์ที่แนะนำใน SQL Server 2012 เช่นสรุป / รวมคอลัมน์สองสามคอลัมน์บนตารางขนาดใหญ่ที่มีหลายคอลัมน์

แม้ว่าดัชนีเหล่านี้มีผลข้างเคียงของการสร้างตารางแบบอ่านอย่างเดียว (ยกเว้นการสลับพาร์ติชัน) แต่สามารถเปลี่ยนประสิทธิภาพของคิวรีแบบรวมภายใต้เงื่อนไขที่เหมาะสม ด้านการอ่านอย่างเดียวสามารถจัดการได้โดยการวางและสร้างดัชนีใหม่หรือข้อมูลการสลับพาร์ติชันอย่างง่ายเข้าไปในตาราง

ฉันตั้งค่าอุปกรณ์ทดสอบอย่างง่ายเพื่อเลียนแบบการตั้งค่าของคุณและเห็นการปรับปรุงที่ดีในประสิทธิภาพ:

USE tempdb
GO

SET NOCOUNT ON
GO

-- Create a large table
IF OBJECT_ID('dbo.largeTable') IS NOT NULL
DROP TABLE dbo.largeTable
GO
CREATE TABLE dbo.largeTable ( 

    [TABLE] VARCHAR(30) NULL,
    FIELD VARCHAR(30) NULL,
    [AFTER] VARCHAR(1000) NULL,
    [DATE] DATETIME,
    SORT_ID INT IDENTITY(1,1),

    pad VARCHAR(100) DEFAULT REPLICATE( '$', 100 )
)
GO

-- Populate table
;WITH cte AS (
SELECT TOP 100000 ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) rn
FROM master.sys.columns c1
    CROSS JOIN master.sys.columns c2
    CROSS JOIN master.sys.columns c3
)
INSERT INTO dbo.largeTable ( [TABLE], FIELD, [AFTER], [DATE] )
SELECT 
    x.tableName, 
    y.field,
    z.[after],
    DATEADD( day, rn % 1111, '1 Jan 2012' )
FROM cte c
    CROSS JOIN ( VALUES ( 'OTB' ), ( 'AAA' ), ( 'BBB' ), ( 'CCCC' ) ) x ( tableName )
    CROSS JOIN ( VALUES ( 'STATUS' ), ( 'TIME' ), ( 'POWER' ) ) y ( field )
    CROSS JOIN ( VALUES ( 'R' ), ( 'X' ), ( 'Z' ), ( 'A' ) ) z ( [after] )

CHECKPOINT

GO 5

EXEC sp_spaceused 'dbo.largeTable'
GO

SELECT MIN([DATE]) xmin, MAX([DATE]) xmax, FORMAT( COUNT(*), '#,#' ) records
FROM dbo.largeTable
GO

-- Optionally clear cache for more comparable results; DO NOT RUN ON PRODUCTION SYSTEM!!
--DBCC DROPCLEANBUFFERS
--DBCC FREEPROCCACHE
--GO

DECLARE @startDate DATETIME2 = SYSUTCDATETIME()

SELECT COUNT(*) AS COUNT
FROM dbo.largeTable
WHERE [AFTER] = 'R' 
  AND [DATE] >= '2014-01-01' 
  AND [DATE] <= '2015-01-01'

SELECT DATEDIFF( millisecond, @startDate, SYSUTCDATETIME() ) diff1
GO

-- Add the non-clustered columnstore
CREATE NONCLUSTERED COLUMNSTORE INDEX _cs ON dbo.largeTable ( [TABLE], FIELD, [AFTER], [DATE] )
GO

-- Optionally clear cache for more comparable results; DO NOT RUN ON PRODUCTION SYSTEM!!
--DBCC DROPCLEANBUFFERS
--DBCC FREEPROCCACHE
--GO

-- Check query again
DECLARE @startDate DATETIME2 = SYSUTCDATETIME()

SELECT COUNT(*) AS COUNT
FROM dbo.largeTable
WHERE [AFTER] = 'R' 
  AND [DATE] >= '2014-01-01' 
  AND [DATE] <= '2015-01-01'

SELECT DATEDIFF( millisecond, @startDate, SYSUTCDATETIME() ) diff2
GO

ผลลัพธ์ของฉัน 6 วินาที v 0.08 วินาที:

ป้อนคำอธิบายรูปภาพที่นี่

โดยสรุปลองสร้างเคสกับเจ้านายของคุณเพื่อเปลี่ยนดัชนีหรืออย่างน้อยก็สร้างกระบวนการข้ามคืนบางอย่างที่ระเบียนเหล่านี้ถูกแกะสลักออกไปยังตาราง / ฐานข้อมูลการรายงานแบบอ่านอย่างเดียวที่คุณสามารถทำงานของคุณและเพิ่มการทำดัชนี เหมาะสมกับปริมาณงานนั้น

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