Ich habe eine relativ große Tabelle (derzeit 2 Millionen Datensätze) und möchte wissen, ob es möglich ist, die Leistung für Ad-hoc-Abfragen zu verbessern. Das Wort Ad-hoc ist hier der Schlüssel. Das Hinzufügen von Indizes ist keine Option (es gibt bereits Indizes für die Spalten, die am häufigsten abgefragt werden).
Ausführen einer einfachen Abfrage, um die 100 zuletzt aktualisierten Datensätze zurückzugeben:
select top 100 * from ER101_ACCT_ORDER_DTL order by er101_upd_date_iso desc
Dauert einige Minuten. Siehe Ausführungsplan unten:
Zusätzliches Detail aus dem Tabellenscan:
SQL Server Execution Times:
CPU time = 3945 ms, elapsed time = 148524 ms.
Der Server ist ziemlich leistungsfähig (vom Speicher 48 GB RAM, 24-Kern-Prozessor), auf dem SQL Server 2008 R2 x64 ausgeführt wird.
Aktualisieren
Ich habe diesen Code gefunden, um eine Tabelle mit 1.000.000 Datensätzen zu erstellen. Ich dachte, ich könnte dann SELECT TOP 100 * FROM testEnvironment ORDER BY mailAddress DESC
auf einigen verschiedenen Servern laufen , um herauszufinden, ob meine Datenträgerzugriffsgeschwindigkeiten auf dem Server schlecht waren.
WITH t1(N) AS (SELECT 1 UNION ALL SELECT 1),
t2(N) AS (SELECT 1 FROM t1 x, t1 y),
t3(N) AS (SELECT 1 FROM t2 x, t2 y),
Tally(N) AS (SELECT TOP 98 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM t3 x, t3 y),
Tally2(N) AS (SELECT TOP 5 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM t3 x, t3 y),
Combinations(N) AS (SELECT DISTINCT LTRIM(RTRIM(RTRIM(SUBSTRING(poss,a.N,2)) + SUBSTRING(vowels,b.N,1)))
FROM Tally a
CROSS JOIN Tally2 b
CROSS APPLY (SELECT 'B C D F G H J K L M N P R S T V W Z SCSKKNSNSPSTBLCLFLGLPLSLBRCRDRFRGRPRTRVRSHSMGHCHPHRHWHBWCWSWTW') d(poss)
CROSS APPLY (SELECT 'AEIOU') e(vowels))
SELECT IDENTITY(INT,1,1) AS ID, a.N + b.N AS N
INTO #testNames
FROM Combinations a
CROSS JOIN Combinations b;
SELECT IDENTITY(INT,1,1) AS ID, firstName, secondName
INTO #testNames2
FROM (SELECT firstName, secondName
FROM (SELECT TOP 1000 --1000 * 1000 = 1,000,000 rows
N AS firstName
FROM #testNames
ORDER BY NEWID()) a
CROSS JOIN (SELECT TOP 1000 --1000 * 1000 = 1,000,000 rows
N AS secondName
FROM #testNames
ORDER BY NEWID()) b) innerQ;
SELECT firstName, secondName,
firstName + '.' + secondName + '@fake.com' AS eMail,
CAST((ABS(CHECKSUM(NEWID())) % 250) + 1 AS VARCHAR(3)) + ' ' AS mailAddress,
(ABS(CHECKSUM(NEWID())) % 152100) + 1 AS jID,
IDENTITY(INT,1,1) AS ID
INTO #testNames3
FROM #testNames2
SELECT IDENTITY(INT,1,1) AS ID, firstName, secondName, eMail,
mailAddress + b.N + b.N AS mailAddress
INTO testEnvironment
FROM #testNames3 a
INNER JOIN #testNames b ON a.jID = b.ID;
--CLEAN UP USELESS TABLES
DROP TABLE #testNames;
DROP TABLE #testNames2;
DROP TABLE #testNames3;
Auf den drei Testservern wurde die Abfrage jedoch fast sofort ausgeführt. Kann jemand das erklären?
Update 2
Vielen Dank für die Kommentare - bitte halten Sie sie auf dem Laufenden ... Sie haben mich dazu veranlasst, den Primärschlüsselindex von nicht gruppiert in gruppiert zu ändern, mit ziemlich interessanten (und unerwarteten?) Ergebnissen.
Nicht geclustert:
SQL Server Execution Times:
CPU time = 3634 ms, elapsed time = 154179 ms.
Clustered:
SQL Server Execution Times:
CPU time = 2650 ms, elapsed time = 52177 ms.
Wie ist das möglich? Wie kann ein Clustered-Index-Scan ohne Index in der Spalte er101_upd_date_iso verwendet werden?
Update 3
Wie angefordert, ist dies das Skript zum Erstellen einer Tabelle:
CREATE TABLE [dbo].[ER101_ACCT_ORDER_DTL](
[ER101_ORG_CODE] [varchar](2) NOT NULL,
[ER101_ORD_NBR] [int] NOT NULL,
[ER101_ORD_LINE] [int] NOT NULL,
[ER101_EVT_ID] [int] NULL,
[ER101_FUNC_ID] [int] NULL,
[ER101_STATUS_CDE] [varchar](2) NULL,
[ER101_SETUP_ID] [varchar](8) NULL,
[ER101_DEPT] [varchar](6) NULL,
[ER101_ORD_TYPE] [varchar](2) NULL,
[ER101_STATUS] [char](1) NULL,
[ER101_PRT_STS] [char](1) NULL,
[ER101_STS_AT_PRT] [char](1) NULL,
[ER101_CHG_COMMENT] [varchar](255) NULL,
[ER101_ENT_DATE_ISO] [datetime] NULL,
[ER101_ENT_USER_ID] [varchar](10) NULL,
[ER101_UPD_DATE_ISO] [datetime] NULL,
[ER101_UPD_USER_ID] [varchar](10) NULL,
[ER101_LIN_NBR] [int] NULL,
[ER101_PHASE] [char](1) NULL,
[ER101_RES_CLASS] [char](1) NULL,
[ER101_NEW_RES_TYPE] [varchar](6) NULL,
[ER101_RES_CODE] [varchar](12) NULL,
[ER101_RES_QTY] [numeric](11, 2) NULL,
[ER101_UNIT_CHRG] [numeric](13, 4) NULL,
[ER101_UNIT_COST] [numeric](13, 4) NULL,
[ER101_EXT_COST] [numeric](11, 2) NULL,
[ER101_EXT_CHRG] [numeric](11, 2) NULL,
[ER101_UOM] [varchar](3) NULL,
[ER101_MIN_CHRG] [numeric](11, 2) NULL,
[ER101_PER_UOM] [varchar](3) NULL,
[ER101_MAX_CHRG] [numeric](11, 2) NULL,
[ER101_BILLABLE] [char](1) NULL,
[ER101_OVERRIDE_FLAG] [char](1) NULL,
[ER101_RES_TEXT_YN] [char](1) NULL,
[ER101_DB_CR_FLAG] [char](1) NULL,
[ER101_INTERNAL] [char](1) NULL,
[ER101_REF_FIELD] [varchar](255) NULL,
[ER101_SERIAL_NBR] [varchar](50) NULL,
[ER101_RES_PER_UNITS] [int] NULL,
[ER101_SETUP_BILLABLE] [char](1) NULL,
[ER101_START_DATE_ISO] [datetime] NULL,
[ER101_END_DATE_ISO] [datetime] NULL,
[ER101_START_TIME_ISO] [datetime] NULL,
[ER101_END_TIME_ISO] [datetime] NULL,
[ER101_COMPL_STS] [char](1) NULL,
[ER101_CANCEL_DATE_ISO] [datetime] NULL,
[ER101_BLOCK_CODE] [varchar](6) NULL,
[ER101_PROP_CODE] [varchar](8) NULL,
[ER101_RM_TYPE] [varchar](12) NULL,
[ER101_WO_COMPL_DATE] [datetime] NULL,
[ER101_WO_BATCH_ID] [varchar](10) NULL,
[ER101_WO_SCHED_DATE_ISO] [datetime] NULL,
[ER101_GL_REF_TRANS] [char](1) NULL,
[ER101_GL_COS_TRANS] [char](1) NULL,
[ER101_INVOICE_NBR] [int] NULL,
[ER101_RES_CLOSED] [char](1) NULL,
[ER101_LEAD_DAYS] [int] NULL,
[ER101_LEAD_HHMM] [int] NULL,
[ER101_STRIKE_DAYS] [int] NULL,
[ER101_STRIKE_HHMM] [int] NULL,
[ER101_LEAD_FLAG] [char](1) NULL,
[ER101_STRIKE_FLAG] [char](1) NULL,
[ER101_RANGE_FLAG] [char](1) NULL,
[ER101_REQ_LEAD_STDATE] [datetime] NULL,
[ER101_REQ_LEAD_ENDATE] [datetime] NULL,
[ER101_REQ_STRK_STDATE] [datetime] NULL,
[ER101_REQ_STRK_ENDATE] [datetime] NULL,
[ER101_LEAD_STDATE] [datetime] NULL,
[ER101_LEAD_ENDATE] [datetime] NULL,
[ER101_STRK_STDATE] [datetime] NULL,
[ER101_STRK_ENDATE] [datetime] NULL,
[ER101_DEL_MARK] [char](1) NULL,
[ER101_USER_FLD1_02X] [varchar](2) NULL,
[ER101_USER_FLD1_04X] [varchar](4) NULL,
[ER101_USER_FLD1_06X] [varchar](6) NULL,
[ER101_USER_NBR_060P] [int] NULL,
[ER101_USER_NBR_092P] [numeric](9, 2) NULL,
[ER101_PR_LIST_DTL] [numeric](11, 2) NULL,
[ER101_EXT_ACCT_CODE] [varchar](8) NULL,
[ER101_AO_STS_1] [char](1) NULL,
[ER101_PLAN_PHASE] [char](1) NULL,
[ER101_PLAN_SEQ] [int] NULL,
[ER101_ACT_PHASE] [char](1) NULL,
[ER101_ACT_SEQ] [int] NULL,
[ER101_REV_PHASE] [char](1) NULL,
[ER101_REV_SEQ] [int] NULL,
[ER101_FORE_PHASE] [char](1) NULL,
[ER101_FORE_SEQ] [int] NULL,
[ER101_EXTRA1_PHASE] [char](1) NULL,
[ER101_EXTRA1_SEQ] [int] NULL,
[ER101_EXTRA2_PHASE] [char](1) NULL,
[ER101_EXTRA2_SEQ] [int] NULL,
[ER101_SETUP_MSTR_SEQ] [int] NULL,
[ER101_SETUP_ALTERED] [char](1) NULL,
[ER101_RES_LOCKED] [char](1) NULL,
[ER101_PRICE_LIST] [varchar](10) NULL,
[ER101_SO_SEARCH] [varchar](9) NULL,
[ER101_SSB_NBR] [int] NULL,
[ER101_MIN_QTY] [numeric](11, 2) NULL,
[ER101_MAX_QTY] [numeric](11, 2) NULL,
[ER101_START_SIGN] [char](1) NULL,
[ER101_END_SIGN] [char](1) NULL,
[ER101_START_DAYS] [int] NULL,
[ER101_END_DAYS] [int] NULL,
[ER101_TEMPLATE] [char](1) NULL,
[ER101_TIME_OFFSET] [char](1) NULL,
[ER101_ASSIGN_CODE] [varchar](10) NULL,
[ER101_FC_UNIT_CHRG] [numeric](13, 4) NULL,
[ER101_FC_EXT_CHRG] [numeric](11, 2) NULL,
[ER101_CURRENCY] [varchar](3) NULL,
[ER101_FC_RATE] [numeric](12, 5) NULL,
[ER101_FC_DATE] [datetime] NULL,
[ER101_FC_MIN_CHRG] [numeric](11, 2) NULL,
[ER101_FC_MAX_CHRG] [numeric](11, 2) NULL,
[ER101_FC_FOREIGN] [numeric](12, 5) NULL,
[ER101_STAT_ORD_NBR] [int] NULL,
[ER101_STAT_ORD_LINE] [int] NULL,
[ER101_DESC] [varchar](255) NULL
) ON [PRIMARY]
SET ANSI_PADDING OFF
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PRT_SEQ_1] [varchar](12) NULL
SET ANSI_PADDING ON
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PRT_SEQ_2] [varchar](120) NULL
SET ANSI_PADDING OFF
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TAX_BASIS] [char](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_RES_CATEGORY] [char](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_DECIMALS] [char](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TAX_SEQ] [varchar](7) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MANUAL] [char](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_LC_RATE] [numeric](12, 5) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_FC_RATE] [numeric](12, 5) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_PL_RATE] [numeric](12, 5) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_DIFF] [char](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_UNIT_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_EXT_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_MIN_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TR_MAX_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PL_UNIT_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PL_EXT_CHRG] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PL_MIN_CHRG] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PL_MAX_CHRG] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TAX_RATE_TYPE] [char](1) NULL
SET ANSI_PADDING ON
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ORDER_FORM] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_FACTOR] [int] NULL
SET ANSI_PADDING OFF
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MGMT_RPT_CODE] [varchar](6) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ROUND_CHRG] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_WHOLE_QTY] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SET_QTY] [numeric](15, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SET_UNITS] [numeric](15, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SET_ROUNDING] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SET_SUB] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TIME_QTY] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_GL_DISTR_PCT] [numeric](7, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_REG_SEQ] [int] NULL
SET ANSI_PADDING ON
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ALT_DESC] [varchar](255) NULL
SET ANSI_PADDING OFF
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_REG_ACCT] [varchar](8) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_DAILY] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_AVG_UNIT_CHRG] [varchar](1) NULL
SET ANSI_PADDING ON
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ALT_DESC2] [varchar](255) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_CONTRACT_SEQ] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ORIG_RATE] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_DISC_PCT] [decimal](17, 10) NULL
SET ANSI_PADDING OFF
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_DTL_EXIST] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ORDERED_ONLY] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHOW_STDATE] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHOW_STTIME] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHOW_ENDATE] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHOW_ENTIME] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHOW_RATE] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHOW_UNITS] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_BASE_RATE] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_COMMIT_QTY] [numeric](11, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MM_QTY_USED] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MM_CHRG_USED] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_TEXT_1] [varchar](50) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_NBR_1] [numeric](13, 3) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_NBR_2] [numeric](13, 3) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_NBR_3] [numeric](13, 3) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PL_BASE_RATE] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_REV_DIST] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_COVER] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_RATE_TYPE] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_USE_SEASONAL] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TAX_EI] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TAXES] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_FC_TAXES] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PL_TAXES] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_FC_QTY] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_LEAD_HRS] [numeric](6, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_STRIKE_HRS] [numeric](6, 2) NULL
SET ANSI_PADDING ON
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_CANCEL_USER_ID] [varchar](10) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ST_OFFSET_HRS] [numeric](7, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_EN_OFFSET_HRS] [numeric](7, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MEMO_FLAG] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MEMO_EXT_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MEMO_EXT_CHRG_PL] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MEMO_EXT_CHRG_TR] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MEMO_EXT_CHRG_FC] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TIME_QTY_EDIT] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SURCHARGE_PCT] [decimal](17, 10) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_INCL_EXT_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_INCL_EXT_CHRG_FC] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_CARRIER] [varchar](6) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SETUP_ID2] [varchar](8) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHIPPABLE] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_CHARGEABLE] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_NBR_ALLOW] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_NBR_START] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_NBR_END] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_SUPPLIER] [varchar](8) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_TRACK_ID] [varchar](40) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_REF_INV_NBR] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_NEW_ITEM_STS] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MSTR_REG_ACCT_CODE] [varchar](8) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ALT_DESC3] [varchar](255) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ALT_DESC4] [varchar](255) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ALT_DESC5] [varchar](255) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SETUP_ROLLUP] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MM_COST_USED] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_AUTO_SHIP_RCD] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_FIXED] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ITEM_EST_TBD] [varchar](3) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ROLLUP_PL_UNIT_CHRG] [numeric](13, 4) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ROLLUP_PL_EXT_CHRG] [numeric](13, 2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_GL_ORD_REV_TRANS] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_DISCOUNT_FLAG] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SETUP_RES_TYPE] [varchar](6) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SETUP_RES_CODE] [varchar](12) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PERS_SCHED_FLAG] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PRINT_STAMP] [datetime] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SHOW_EXT_CHRG] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PRINT_SEQ_NBR] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_PAY_LOCATION] [varchar](3) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_MAX_RM_NIGHTS] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_USE_TIER_COST] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_UNITS_SCHEME_CODE] [varchar](6) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_ROUND_TIME] [varchar](2) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_LEVEL] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_SETUP_PARENT_ORD_LINE] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_BADGE_PRT_STS] [varchar](1) NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_EVT_PROMO_SEQ] [int] NULL
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD [ER101_REG_TYPE] [varchar](12) NULL
/****** Object: Index [PK__ER101_ACCT_ORDER] Script Date: 04/15/2012 20:24:37 ******/
ALTER TABLE [dbo].[ER101_ACCT_ORDER_DTL] ADD CONSTRAINT [PK__ER101_ACCT_ORDER] PRIMARY KEY CLUSTERED
(
[ER101_ORD_NBR] ASC,
[ER101_ORD_LINE] ASC,
[ER101_ORG_CODE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50) ON [PRIMARY]
Die Tabelle hat eine Größe von 2,8 GB und eine Indexgröße von 3,9 GB.
quelle
Table Scan
Gibt einen Heap an (kein Clustered-Index). Der erste Schritt besteht also darin , Ihrer Tabelle einen guten, schnellen Clustered-Index hinzuzufügen . Der zweite Schritt könnte darin bestehen, zu untersuchen, ob ein nicht gruppierter Index fürer101_upd_date_iso
hilfreich ist (und keine anderen Leistungsnachteile verursacht)er101_upd_date_iso
Spalte hinzugefügt haben , können Sie wahrscheinlich auch die Operation "Sortieren" in Ihrem AusführungsplanAntworten:
Einfache Antwort: NEIN. Sie können Ad-hoc-Abfragen für eine 238-Spaltentabelle mit einem Füllfaktor von 50% für den Clustered-Index nicht unterstützen.
Detaillierte Antwort:
Wie ich in anderen Antworten zu diesem Thema ausgeführt habe, ist Indexdesign sowohl Kunst als auch Wissenschaft, und es gibt so viele Faktoren zu berücksichtigen, dass es nur wenige, wenn überhaupt, feste Regeln gibt. Sie müssen Folgendes berücksichtigen: Das Volumen der DML-Operationen im Vergleich zu SELECTs, das Festplattensubsystem, andere Indizes / Trigger in der Tabelle, die Verteilung der Daten in der Tabelle sind Abfragen unter Verwendung von SARGable WHERE-Bedingungen und einige andere Dinge, an die ich mich nicht einmal richtig erinnern kann jetzt.
Ich kann sagen, dass bei Fragen zu diesem Thema keine Hilfe gegeben werden kann, ohne die Tabelle selbst, ihre Indizes, Trigger usw. zu verstehen. Nachdem Sie die Tabellendefinition veröffentlicht haben (warten Sie immer noch auf die Indizes, aber nur die Tabellendefinition zeigt darauf 99% der Ausgabe) Ich kann einige Vorschläge machen.
Erstens, wenn die Tabellendefinition korrekt ist (238 Spalten, 50% Füllfaktor), können Sie den Rest der Antworten / Ratschläge hier so gut wie ignorieren ;-). Es tut mir leid, hier weniger als politisch zu sein, aber im Ernst, es ist eine wilde Gänsejagd, ohne die Einzelheiten zu kennen. Und jetzt, da wir die Tabellendefinition sehen, wird ziemlich viel klarer, warum eine einfache Abfrage so lange dauern würde, selbst wenn die Testabfragen (Update Nr. 1) so schnell ausgeführt wurden.
Das Hauptproblem hier (und in vielen Situationen mit schlechter Leistung) ist die schlechte Datenmodellierung. 238 Spalten sind nicht verboten, genauso wie 999 Indizes nicht verboten sind, aber es ist auch im Allgemeinen nicht sehr klug.
Empfehlungen:
ANSI_PADDING OFF
ist störend, ganz zu schweigen von der Inkonsistenz innerhalb der Tabelle aufgrund der verschiedenen Spaltenzusätze im Laufe der Zeit. Ich bin mir nicht sicher, ob Sie das jetzt beheben können, aber im Idealfall hätten Sie immerANSI_PADDING ON
oder zumindest die gleiche Einstellung für alleALTER TABLE
Anweisungen.PRIMARY
Daten nicht dort abzulegen, da dort SQL SERVER alle Daten und Metadaten zu Ihren Objekten speichert. Sie erstellen Ihre Tabelle und Ihren Clustered-Index (da dies die Daten für die Tabelle sind) auf[Tables]
und alle Nicht-Clustered-Indizes auf[Indexes]
WHERE
Bedingung enthalten, sollten Sie dies in die führende Spalte des Clustered-Index verschieben. Angenommen, es wird häufiger als "ER101_ORD_NBR" verwendet. Wenn "ER101_ORD_NBR" häufiger verwendet wird, behalten Sie es bei. Unter der Annahme, dass die Feldnamen "OrganizationCode" und "OrderNumber" bedeuten, scheint "OrgCode" eine bessere Gruppierung zu sein, die möglicherweise mehrere "OrderNumbers" enthält.CHAR(2)
stattdessen anstelle von,VARCHAR(2)
da dadurch ein Byte im Zeilenkopf gespeichert wird, der variable Breitengrößen verfolgt und sich über Millionen von Zeilen summiert.SELECT *
die Verwendung die Leistung. Dies erfordert nicht nur, dass SQL Server alle Spalten zurückgibt und daher mit größerer Wahrscheinlichkeit einen Clustered Index Scan unabhängig von Ihren anderen Indizes durchführt, sondern SQL Server benötigt auch Zeit, um zur Tabellendefinition zu gelangen und*
in alle Spaltennamen zu übersetzen . Es sollte etwas schneller sein, alle 238 Spaltennamen in derSELECT
Liste anzugeben, obwohl dies das Scan-Problem nicht beheben kann. Aber brauchen Sie wirklich jemals alle 238 Spalten gleichzeitig?Viel Glück!
UPDATE
Der Vollständigkeit halber sollte die Frage "Wie kann die Leistung einer großen Tabelle für Ad-hoc-Abfragen verbessert werden?" Vermerkt werden, dass dies in diesem speziellen Fall nicht hilfreich ist, wenn jemand SQL Server 2012 (oder neuer) verwendet Wenn diese Zeit gekommen ist) und wenn die Tabelle nicht aktualisiert wird, ist die Verwendung von Columnstore-Indizes eine Option. Weitere Informationen zu dieser neuen Funktion finden Sie hier: http://msdn.microsoft.com/en-us/library/gg492088.aspx (Ich glaube, diese wurden ab SQL Server 2014 aktualisierbar gemacht).
UPDATE 2
Zusätzliche Überlegungen sind:
INT
,BIGINT
,TINYINT
,SMALLINT
,CHAR
,NCHAR
,BINARY
,DATETIME
,SMALLDATETIME
,MONEY
, etc.) und mehr als 50 % der Zeilen sindNULL
, dann sollten Sie dieSPARSE
Option aktivieren, die in SQL Server 2008 verfügbar wurde. Weitere Informationen finden Sie auf der MSDN-Seite für die Verwendung sparsamer Spalten .quelle
*
Ohne diese zweifelhafte gibt es genügend Argumente dagegenEs gibt einige Probleme mit dieser Abfrage (und diese gelten für jede Abfrage).
Fehlender Index
Das Fehlen eines Index für die
er101_upd_date_iso
Spalte ist das Wichtigste, wie Oded bereits erwähnt hat.Ohne übereinstimmenden Index (dessen Fehlen einen Tabellenscan verursachen könnte) besteht keine Möglichkeit, schnelle Abfragen für große Tabellen auszuführen.
Wenn Sie keine Indizes hinzufügen können (aus verschiedenen Gründen, einschließlich der sinnlosen Erstellung eines Index für nur eine Ad-hoc-Abfrage ), würde ich einige Problemumgehungen vorschlagen (die für Ad-hoc-Abfragen verwendet werden können):
1. Verwenden Sie temporäre Tabellen
Erstellen Sie eine temporäre Tabelle für eine Teilmenge (Zeilen und Spalten) der Daten, an denen Sie interessiert sind. Die temporäre Tabelle sollte viel kleiner als die ursprüngliche Quelltabelle sein, kann einfach indiziert werden (falls erforderlich) und kann eine Teilmenge der Daten zwischengespeichert werden, an denen Sie interessiert sind.
Um eine temporäre Tabelle zu erstellen, können Sie Code (nicht getestet) wie folgt verwenden:
Vorteile:
view
.Nachteile:
2. Allgemeiner Tabellenausdruck - CTE
Persönlich verwende ich CTE häufig bei Ad-hoc-Abfragen - es hilft sehr beim Erstellen (und Testen) einer Abfrage Stück für Stück.
Siehe Beispiel unten (die Abfrage beginnt mit
WITH
).Vorteile:
Nachteile:
3. Erstellen Sie Ansichten
Ähnlich wie oben, jedoch Ansichten anstelle von temporären Tabellen erstellen (wenn Sie häufig mit denselben Abfragen spielen und über eine MS SQL-Version verfügen, die indizierte Ansichten unterstützt.
Sie können Ansichten oder indizierte Ansichten für eine Teilmenge von Daten erstellen, an denen Sie interessiert sind, und Abfragen für die Ansicht ausführen. Diese sollten nur eine interessante Teilmenge von Daten enthalten, die viel kleiner als die gesamte Tabelle ist.
Vorteile:
Nachteile:
Alle Spalten auswählen
Es ist nicht gut, star query (
SELECT * FROM
) auf einem großen Tisch auszuführen ...Wenn Sie große Spalten haben (wie lange Zeichenfolgen), dauert es viel Zeit, diese von der Festplatte zu lesen und über das Netzwerk zu übertragen.
Ich würde versuchen, durch
*
Spaltennamen zu ersetzen, die Sie wirklich brauchen.Wenn Sie alle Spalten benötigen, versuchen Sie, die Abfrage in etwas wie (unter Verwendung eines gemeinsamen Datenausdrucks ) umzuschreiben :
Dirty liest
Das Letzte, was die Ad-hoc-Abfrage beschleunigen könnte, ist das Zulassen von Dirty Reads mit Tabellenhinweisen
WITH (NOLOCK)
.Anstelle eines Hinweises können Sie die Transaktionsisolationsstufe so einstellen , dass sie nicht festgeschrieben lautet:
oder legen Sie die richtige SQL Management Studio-Einstellung fest.
Ich gehe davon aus, dass für Ad-hoc-Anfragen Dirty Reads gut genug sind.
quelle
SELECT *
- zwingt SQL Server, den Clustered-Index zu verwenden. Zumindest sollte es so sein. Ich sehe keinen wirklichen Grund für einen nicht gruppierten Deckungsindex ... der die gesamte Tabelle abdeckt :)Dort wird ein Tabellenscan durchgeführt. Dies bedeutet, dass für Sie kein Index definiert
er101_upd_date_iso
ist. Wenn diese Spalte Teil eines vorhandenen Index ist, kann der Index nicht verwendet werden (möglicherweise handelt es sich nicht um die primäre Indexerspalte).Das Hinzufügen fehlender Indizes trägt zur unbegrenzten Leistung bei.
Das bedeutet nicht, dass sie in dieser Abfrage verwendet werden (und wahrscheinlich auch nicht).
Ich empfehle, die Ursachen für schlechte Leistung in SQL Server von Gail Shaw, Teil 1 und Teil 2 , zu lesen .
quelle
er101_upd_date_iso
es sich um einen großen Varchar oder einen Int handelt, ändert sich die Leistung erheblich.In der Frage wird speziell angegeben, dass die Leistung für Ad-hoc- Abfragen verbessert werden muss und dass keine Indizes hinzugefügt werden können. Was kann man also tun, um die Leistung an einem Tisch zu verbessern?
Da wir Ad-hoc-Abfragen berücksichtigen, können die WHERE-Klausel und die ORDER BY-Klausel eine beliebige Kombination von Spalten enthalten. Dies bedeutet, dass fast unabhängig davon, welche Indizes für die Tabelle platziert werden, einige Abfragen erforderlich sind, die einen Tabellenscan erfordern, wie oben im Abfrageplan einer Abfrage mit schlechter Leistung dargestellt.
Nehmen wir vor diesem Hintergrund an, dass in der Tabelle außer einem Clustered-Index für den Primärschlüssel überhaupt keine Indizes vorhanden sind. Lassen Sie uns nun überlegen, welche Optionen wir haben, um die Leistung zu maximieren.
Defragmentieren Sie den Tisch
Solange wir einen Clustered-Index haben, können wir die Tabelle mit DBCC INDEXDEFRAG (veraltet) oder vorzugsweise ALTER INDEX defragmentieren . Dadurch wird die Anzahl der zum Scannen der Tabelle erforderlichen Festplattenlesevorgänge minimiert und die Geschwindigkeit verbessert.
Verwenden Sie die schnellstmöglichen Festplatten. Sie sagen nicht, welche Festplatten Sie verwenden, sondern ob Sie SSDs verwenden können.
Tempdb optimieren. Legen Sie tempdb auf die schnellstmöglichen Festplatten, wieder SSDs. Siehe diesen SO-Artikel und diesen RedGate-Artikel .
Wie in anderen Antworten angegeben, gibt die Verwendung einer selektiveren Abfrage weniger Daten zurück und sollte daher schneller sein.
Lassen Sie uns nun überlegen, was wir tun können, wenn wir Indizes hinzufügen dürfen.
Wenn wir nicht über Ad-hoc-Abfragen sprechen würden, würden wir Indizes speziell für die begrenzte Anzahl von Abfragen hinzufügen, die für die Tabelle ausgeführt werden. Was kann getan werden, um die Geschwindigkeit die meiste Zeit zu verbessern, da wir über Ad-hoc- Abfragen sprechen ?
Bearbeiten
Ich habe einige Tests für eine "große" Tabelle mit 22 Millionen Zeilen durchgeführt. Meine Tabelle hat nur sechs Spalten, enthält aber 4 GB Daten. Mein Computer ist ein seriöser Desktop mit 8 GB RAM und einer Quad-Core-CPU und verfügt über eine einzelne Agility 3-SSD.
Ich habe alle Indizes außer dem Primärschlüssel in der ID-Spalte entfernt.
Eine ähnliche Abfrage wie das in der Frage angegebene Problem dauert 5 Sekunden, wenn der SQL Server zuerst und anschließend 3 Sekunden neu gestartet wird. Der Datenbankoptimierungsberater empfiehlt offensichtlich, einen Index hinzuzufügen, um diese Abfrage zu verbessern, mit einer geschätzten Verbesserung von> 99%. Das Hinzufügen eines Index führt zu einer Abfragezeit von effektiv Null.
Interessant ist auch, dass mein Abfrageplan mit Ihrem identisch ist (mit dem Clustered-Index-Scan), der Index-Scan jedoch 9% der Abfragekosten und die Sortierung die restlichen 91% ausmacht. Ich kann nur davon ausgehen, dass Ihre Tabelle eine enorme Datenmenge enthält und / oder Ihre Festplatten sehr langsam sind oder sich über eine sehr langsame Netzwerkverbindung befinden.
quelle
Selbst wenn Sie Indizes für einige Spalten haben, die in einigen Abfragen verwendet werden, zeigt die Tatsache, dass Ihre Ad-hoc-Abfrage einen Tabellenscan verursacht, dass Sie nicht über genügend Indizes verfügen, um diese Abfrage effizient abzuschließen.
Insbesondere für Datumsbereiche ist es schwierig, gute Indizes hinzuzufügen.
Wenn Sie sich nur Ihre Abfrage ansehen, muss die Datenbank alle Datensätze nach der ausgewählten Spalte sortieren, um die ersten n Datensätze zurückgeben zu können.
Führt die Datenbank auch einen vollständigen Tabellenscan ohne die order by-Klausel durch? Hat die Tabelle einen Primärschlüssel - ohne PK muss die Datenbank härter arbeiten, um die Sortierung durchzuführen?
quelle
select top 100 * from ER101_ACCT_ORDER_DTL
Ein Index ist ein B-Baum, in dem jeder Blattknoten auf eine Reihe von Zeilen verweist (in der internen SQL-Terminologie als "Seite" bezeichnet). In diesem Fall handelt es sich bei dem Index um einen nicht gruppierten Index.
Clustered Index ist ein Sonderfall, bei dem die Blattknoten die "Reihe von Zeilen" haben (anstatt auf sie zu zeigen). deswegen...
1) Es kann nur einen Clustered-Index für die Tabelle geben.
Dies bedeutet auch, dass die gesamte Tabelle als Clustered-Index gespeichert wird. Aus diesem Grund wurde der Index-Scan anstelle eines Tabellenscans angezeigt.
2) Eine Operation, die einen Clustered-Index verwendet, ist im Allgemeinen schneller als ein Nicht-Clustered-Index
Lesen Sie mehr unter http://msdn.microsoft.com/en-us/library/ms177443.aspx
Für das Problem, das Sie haben, sollten Sie wirklich in Betracht ziehen, diese Spalte einem Index hinzuzufügen, da Sie sagten, dass das Hinzufügen eines neuen Index (oder einer Spalte zu einem vorhandenen Index) die INSERT / UPDATE-Kosten erhöht. Es ist jedoch möglicherweise möglich, einen nicht ausgelasteten Index (oder eine Spalte aus einem vorhandenen Index) zu entfernen, um ihn durch 'er101_upd_date_iso' zu ersetzen.
Wenn Indexänderungen nicht möglich sind, empfehle ich, eine Statistik zur Spalte hinzuzufügen. Dies kann zu Problemen führen, wenn die Spalten mit indizierten Spalten korrelieren
http://msdn.microsoft.com/en-us/library/ms188038.aspx
Übrigens erhalten Sie viel mehr Hilfe, wenn Sie das Tabellenschema von ER101_ACCT_ORDER_DTL veröffentlichen können. und die vorhandenen Indizes auch ..., wahrscheinlich könnte die Abfrage neu geschrieben werden, um einige von ihnen zu verwenden.
quelle
Einer der Gründe, warum Ihr 1M-Test schneller ausgeführt wurde, ist wahrscheinlich, dass sich die temporären Tabellen vollständig im Speicher befinden und nur dann auf die Festplatte übertragen werden, wenn auf Ihrem Server Speicherdruck herrscht. Sie können entweder Ihre Abfrage neu erstellen, um die Reihenfolge zu entfernen, einen guten Clustered-Index und Deckungsindex (e) hinzufügen, wie zuvor erwähnt, oder die DMV abfragen, um den E / A-Druck zu überprüfen, um festzustellen, ob Hardware zusammenhängt.
quelle
Ich weiß, dass Sie gesagt haben, dass das Hinzufügen von Indizes keine Option ist, aber dies wäre die einzige Option, um Ihren Tabellenscan zu eliminieren. Wenn Sie einen Scan durchführen, liest SQL Server alle 2 Millionen Zeilen in der Tabelle, um Ihre Abfrage zu erfüllen.
Dieser Artikel enthält weitere Informationen, aber denken Sie daran: Suchen = gut, Scannen = schlecht.
Zweitens, können Sie die Auswahl * nicht entfernen und nur die Spalten auswählen, die Sie benötigen? Drittens keine "wo" -Klausel? Selbst wenn Sie einen Index haben, da Sie alles lesen, erhalten Sie am besten einen Index-Scan (der besser ist als ein Tabellenscan, aber keine Suche, auf die Sie abzielen sollten).
quelle
Ich weiß, dass es von Anfang an eine ziemliche Zeit war ... In all diesen Antworten steckt viel Weisheit. Eine gute Indizierung ist das erste, wenn Sie versuchen, eine Abfrage zu verbessern. Na ja, fast der erste. Das Erste (sozusagen) ist, Änderungen am Code vorzunehmen, damit dieser effizient ist. Wenn also eine Abfrage ohne WHERE vorliegt oder wenn die WHERE-Bedingung nicht selektiv genug ist, gibt es nur einen Weg, um die Daten abzurufen: TABLE SCAN (INDEX SCAN). Wenn alle Spalten einer Tabelle benötigt werden, wird TABLE SCAN verwendet - keine Frage. Dies kann je nach Art der Datenorganisation ein Heap-Scan oder ein Clustered-Index-Scan sein. Die einzige letzte Möglichkeit, die Dinge zu beschleunigen (wenn überhaupt möglich), besteht darin, sicherzustellen, dass so viele Kerne wie möglich für den Scan verwendet werden: OPTION (MAXDOP 0). Ich ignoriere natürlich das Thema Speicherung
quelle