89

比較的大きなテーブル (現在 200 万レコード) があり、アドホック クエリのパフォーマンスを改善できるかどうかを知りたいです。ここではアドホックという言葉が重要です。インデックスを追加することはできません (最も頻繁にクエリされる列には既にインデックスが存在します)。

単純なクエリを実行して、最近更新された 100 件のレコードを返します。

select top 100 * from ER101_ACCT_ORDER_DTL order by er101_upd_date_iso desc

数分かかります。以下の実行計画を参照してください。

ここに画像の説明を入力

テーブル スキャンからの追加の詳細:

ここに画像の説明を入力

SQL Server Execution Times:
  CPU time = 3945 ms,  elapsed time = 148524 ms.

サーバーは非常に強力です (メモリ 48GB RAM、24 コア プロセッサから) sql server 2008 r2 x64 を実行しています。

アップデート

1,000,000 レコードのテーブルを作成するこのコードを見つけました。SELECT TOP 100 * FROM testEnvironment ORDER BY mailAddress DESC次に、いくつかの異なるサーバーで実行して、サーバーでのディスクアクセス速度が遅いかどうかを確認できると考えました.

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;

しかし、3 台​​のテスト サーバーでは、クエリはほぼ瞬時に実行されました。誰でもこれを説明できますか?

ここに画像の説明を入力

更新 2

コメントありがとうございます。コメントをお待ちしております...主キー インデックスを非クラスター化からクラスター化に変更してみて、かなり興味深い (そして予想外の?) 結果が得られました。

クラスタ化されていない:

ここに画像の説明を入力

SQL Server Execution Times:
  CPU time = 3634 ms,  elapsed time = 154179 ms.

クラスター化:

ここに画像の説明を入力

SQL Server Execution Times:
  CPU time = 2650 ms,  elapsed time = 52177 ms.

これはどのように可能ですか?er101_upd_date_iso 列にインデックスがない場合、クラスター化インデックス スキャンをどのように使用できますか?

アップデート 3

要求どおり - これはテーブル作成スクリプトです。

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]

テーブルのサイズは 2.8 GB で、インデックスのサイズは 3.9 GB です。

4

9 に答える 9

65

簡単な答え: いいえ。クラスター化インデックスの FILL FACTOR が 50% の 238 列のテーブルでアドホック クエリを実行することはできません。

詳細な回答:

このトピックに関する他の回答で述べたように、インデックスの設計は芸術と科学の両方であり、考慮すべき要素が非常に多いため、厳密で迅速なルールはほとんどありません。考慮する必要があるのは、DML 操作と SELECT の量、ディスク サブシステム、テーブル上の他のインデックス/トリガー、テーブル内のデータの分散、SARGable WHERE 条件を使用したクエリ、および私が正しく覚えていない他のいくつかのことです。今。

テーブル自体、そのインデックス、トリガーなどを理解せずに、このトピックに関する質問に対して助けを与えることはできないと言えます。テーブル定義を投稿したので (まだインデックスを待っていますが、テーブル定義だけが問題の 99%) 私はいくつかの提案を提供できます。

まず、テーブル定義が正確である場合 (238 列、50% のフィル ファクター)、残りの回答/アドバイスはほとんど無視できます ;-)。ここで政治的でなくて申し訳ありませんが、真剣に、詳細を知らずに野生のガチョウの追跡です. テーブル定義を見ると、テスト クエリ (更新 #1) が非常に高速に実行された場合でも、単純なクエリに時間がかかる理由がかなり明確になります。

ここでの (そして多くの低パフォーマンスの状況での) 主な問題は、不適切なデータ モデリングです。999 個のインデックスを持つことが禁止されていないように、238 列も禁止されていませんが、一般的にあまり賢明ではありません。

推奨事項:

  1. まず、このテーブルを改造する必要があります。これがデータ ウェアハウス テーブルである場合は可能ですが、そうでない場合は、これらのフィールドを複数のテーブルに分割する必要があり、すべて同じ PK を持つことができます。マスター レコード テーブルがあり、子テーブルは共通に関連付けられた属性に基づく依存情報であり、それらのテーブルの PK はマスター テーブルの PK と同じであり、したがってマスター テーブルの FK でもあります。マスター テーブルとすべての子テーブルの間には 1 対 1 の関係があります。
  2. の使用ANSI_PADDING OFFは厄介であり、時間の経過とともにさまざまな列が追加されるため、テーブル内で一貫性がないことは言うまでもありません。今すぐ修正できるかどうかはわかりませんが、理想的には、常にANSI_PADDING ON、または少なくともすべてのALTER TABLEステートメントで同じ設定を使用することをお勧めします。
  3. テーブルとインデックスの 2 つの追加ファイル グループを作成することを検討してください。PRIMARYSQL SERVER がオブジェクトに関するすべてのデータとメタデータを格納する場所であるため、自分のものを入れないことをお勧めします。テーブルとクラスター化インデックス (テーブルのデータであるため)[Tables]およびすべての非クラスター化インデックスを作成します。[Indexes]
  4. フィル ファクターを 50% から増やします。この低い数値が、インデックス スペースがデータ スペースよりも大きい理由である可能性があります。インデックスの再構築を行うと、データに使用される最大 4k (合計 8​​k ページ サイズのうち) でデータ ページが再作成されるため、テーブルが広い領域に分散されます。
  5. ほとんどまたはすべてのクエリのWHERE条件に "ER101_ORG_CODE" が含まれている場合は、それをクラスター化インデックスの先頭の列に移動することを検討してください。「ER101_ORD_NBR」よりも使用頻度が高いと想定。「ER101_ORD_NBR」がより頻繁に使用される場合は、そのままにしておきます。フィールド名が「OrganizationCode」と「OrderNumber」を意味すると仮定すると、「OrgCode」はその中に複数の「OrderNumbers」を持つ可能性のあるより良いグループ化です。
  6. 些細な点ですが、「ER101_ORG_CODE」が常に 2 文字の場合は、可変幅サイズを追跡し、数百万行以上を追加する行ヘッダーにバイトを保存するCHAR(2)代わりに使用します。VARCHAR(2)
  7. ここで他の人が述べたように、使用SELECT *するとパフォーマンスが低下します。SQL Server がすべての列を返す必要があるため、他のインデックスに関係なくクラスター化インデックス スキャンを実行する可能性が高くなるだけでなく、SQL Server がテーブル定義に移動*してすべての列名に変換するのにも時間がかかります。 . リスト内の 238 個の列名すべてを指定する方がわずかにSELECT高速ですが、スキャンの問題には役立ちません。しかし、238 列すべてを同時に必要とすることはありますか?

幸運を!

更新
「アドホック クエリの大きなテーブルでパフォーマンスを向上させる方法」という質問を完全にするために、この特定のケースでは役に立たないが、誰かが SQL Server 2012 (またはそれ以降) を使用している場合は、その時が来たら) IF テーブルが更新されていない場合は、列ストア インデックスを使用するオプションがあります。この新機能の詳細については、http: //msdn.microsoft.com/en-us/library/gg492088.aspxを参照してください (これらは、SQL Server 2014 から更新可能になるように作成されたと思います)。

UPDATE 2
追加の考慮事項は次のとおりです。

  • クラスター化インデックスで圧縮を有効にします。このオプションは SQL Server 2008 で利用できるようになりましたが、Enterprise Edition のみの機能です。ただし、SQL Server 2016 SP1の時点で、データ圧縮はすべてのエディションで利用できるようになりました。行とページの圧縮の詳細については、データ圧縮の MSDN ページを参照してください。
  • データ圧縮を使用できない場合、または特定のテーブルにあまりメリットがない場合は、固定長型 ( INTBIGINTTINYINTSMALLINTCHARNCHAR、 、BINARYDATETIMESMALLDATETIMEMONEY、 など) で 50 をはるかに超える列がある場合行の % が である場合は、SQL Server 2008 で利用可能になったオプションをNULL有効にすることを検討してください。詳細については、MSDN ページのUse Sparse Columnsを参照してください。SPARSE
于 2012-04-16T03:15:23.747 に答える
55

このクエリにはいくつかの問題があります (これはすべてのクエリに当てはまります)。

インデックスの欠如

Odedが既に述べたように、列にインデックスがないer101_upd_date_isoことは最も重要なことです。

一致するインデックスがないと (テーブル スキャンが発生する可能性があります)、大きなテーブルに対して高速なクエリを実行する機会はありません。

インデックスを追加できない場合 ( 1 つのアドホック クエリに対してインデックスを作成しても意味がないなど、さまざまな理由で)、いくつかの回避策をお勧めします (アドホック クエリに使用できます)。

1. 一時テーブルを使用する

関心のあるデータのサブセット (行と列) に一時テーブルを作成します。一時テーブルは、元のソース テーブルよりもはるかに小さくする必要があり、(必要に応じて) 簡単にインデックスを作成でき、関心のあるデータのサブセットをキャッシュできます。

一時テーブルを作成するには、次のようなコード (テストされていません) を使用できます。

-- copy records from last month to temporary table
INSERT INTO
   #my_temporary_table
SELECT
    *
FROM
    er101_acct_order_dtl WITH (NOLOCK)
WHERE 
    er101_upd_date_iso > DATEADD(month, -1, GETDATE())

-- you can add any index you need on temp table
CREATE INDEX idx_er101_upd_date_iso ON #my_temporary_table(er101_upd_date_iso)

-- run other queries on temporary table (which can be indexed)
SELECT TOP 100
    * 
FROM 
    #my_temporary_table 
ORDER BY 
    er101_upd_date_iso DESC

長所:

  • データの任意のサブセットに対して簡単に実行できます。
  • 管理が簡単 -一時的テーブルです。
  • のようなシステム全体のパフォーマンスには影響しませんview
  • 一時テーブルにインデックスを付けることができます。
  • あなたはそれを気にする必要はありません - それは一時的なものです:)。

短所:

  • これはデータのスナップショットですが、ほとんどのアドホック クエリにはおそらくこれで十分です。

2. 共通テーブル式 -- CTE

個人的には、アドホック クエリでCTEをよく使用します。クエリを少しずつ構築 (およびテスト) するのに非常に役立ちます。

以下の例を参照してください ( で始まるクエリWITH)。

長所:

  • 大きなビューから始めて、本当に必要なものを選択してフィルタリングするのは簡単です。
  • 簡単にテストできます。

短所:

  • CDE を嫌う人もいます -- CDE クエリは長くて理解しにくいようです。

3. ビューを作成する

上記と同様ですが、一時テーブルの代わりにビューを作成します (同じクエリを頻繁に使用し、インデックス付きビューをサポートする MS SQL バージョンを使用している場合)。

関心のあるデータのサブセットでビューまたはインデックス付きビューを作成し、ビューでクエリを実行できます。これには、テーブル全体よりもはるかに小さいデータの興味深いサブセットのみが含まれている必要があります。

長所:

  • 簡単にできます。
  • ソースデータで最新です。

短所:

  • 定義されたデータのサブセットに対してのみ可能です。
  • 更新率の高い大きなテーブルでは効率が悪い可能性があります。
  • 管理するのはそれほど簡単ではありません。
  • システム全体のパフォーマンスに影響を与える可能性があります。
  • MS SQL のすべてのバージョンでインデックス付きビューが利用できるかどうかはわかりません。

すべての列の選択

大きなテーブルでスター クエリ( ) を実行するSELECT * FROMのは良くありません...

大きな列 (長い文字列など) がある場合、それらをディスクから読み取ってネットワーク経由で渡すのに多くの時間がかかります。

*本当に必要な列名に置き換えてみます。

または、すべての列が必要な場合は、クエリを次のように書き直してみてください (一般的なデータ式を使用):

;WITH recs AS (
    SELECT TOP 100 
        id as rec_id -- select primary key only
    FROM 
        er101_acct_order_dtl 
    ORDER BY 
        er101_upd_date_iso DESC
)
SELECT
    er101_acct_order_dtl.*
FROM
    recs
    JOIN
      er101_acct_order_dtl
    ON
      er101_acct_order_dtl.id = recs.rec_id
ORDER BY 
    er101_upd_date_iso DESC 

ダーティリード

アドホック クエリを高速化できる最後のことは、テーブル ヒントを使用したダーティ リードを許可することです。WITH (NOLOCK)

ヒントの代わりに、コミットされていない読み取りにトランザクション分離レベルを設定できます。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

または適切な SQL Management Studio 設定を設定します。

アドホック クエリではダーティ リードで十分だと思います。

于 2012-04-05T09:32:47.077 に答える
13

そこでテーブル スキャンを取得しています。つまり、 にインデックスが定義されていないer101_upd_date_isoか、その列が既存のインデックスの一部である場合、インデックスを使用できません (おそらくプライマリ インデクサー列ではありません)。

不足しているインデックスを追加すると、パフォーマンスが際限なく向上します。

最も頻繁にクエリされる列には既にインデックスがあります

これは、それらがこのクエリで使用されているという意味ではありません (おそらく使用されていません)。

Gail Shaw 著の Finding the Causes of Poor Performance in SQL Server のパート 1パート 2を読むことをお勧めします。

于 2012-04-05T08:59:07.993 に答える
7

この質問では、アドホッククエリのパフォーマンスを改善する必要があり、インデックスを追加できないことが具体的に述べられています。それを額面通りに考えると、どのテーブルでもパフォーマンスを向上させるために何ができるでしょうか?

アドホック クエリを検討しているため、WHERE 句と ORDER BY 句には任意の列の組み合わせを含めることができます。これは、テーブルに配置されているインデックスにほとんど関係なく、パフォーマンスの低いクエリのクエリ プランで示したように、テーブル スキャンを必要とするクエリがいくつかあることを意味します。

これを考慮して、主キーのクラスター化インデックスを除いて、テーブルにインデックスがまったくないと仮定しましょう。次に、パフォーマンスを最大化するために必要なオプションを考えてみましょう。

  • テーブルの最適化

    クラスター化されたインデックスがある限り、DBCC INDEXDEFRAG (非推奨) またはできればALTER INDEXを使用してテーブルを最適化できます。これにより、テーブルのスキャンに必要なディスク読み取りの数が最小限に抑えられ、速度が向上します。

  • 可能な限り高速なディスクを使用してください。使用しているディスクはわかりませんが、SSD を使用できるかどうかはわかりません。

  • tempdb を最適化します。tempdb を可能な限り高速なディスク (ここでも SSD) に配置します。このSO 記事と このRedGate 記事を参照してください。

  • 他の回答で述べたように、より選択的なクエリを使用すると返されるデータが少なくなるため、高速になるはずです。

ここで、インデックスを追加できる場合に何ができるかを考えてみましょう。

アドホック クエリについて話していない場合は、テーブルに対して実行される限られた一連のクエリ専用にインデックスを追加します。アドホッククエリについて話しているので、ほとんどの場合、速度を向上させるために何ができるでしょうか?

  • 各列に 1 つの列インデックスを追加します。これにより、SQL Server は、少なくとも大部分のクエリの速度を向上させるために何かを使用できるようになりますが、最適ではありません。
  • 最も一般的なクエリに特定のインデックスを追加して、それらが最適化されるようにします。
  • パフォーマンスの低いクエリを監視して、必要に応じて特定のインデックスを追加します。

編集

2200 万行の「大きな」テーブルでいくつかのテストを実行しました。テーブルには 6 つの列しかありませんが、4 GB のデータが含まれています。私のマシンは、8Gb RAM とクアッド コア CPU を搭載した立派なデスクトップで、Agility 3 SSD を 1 つ搭載しています。

Id 列の主キー以外のすべてのインデックスを削除しました。

質問で与えられた問題と同様のクエリは、SQL サーバーが最初に再起動された場合に 5 秒かかり、その後に 3 秒かかります。データベース チューニング アドバイザーは、このクエリを改善するためにインデックスを追加することを明らかに推奨しており、改善率は 99% 以上と推定されています。インデックスを追加すると、実質的にクエリ時間がゼロになります。

また興味深いのは、私のクエリ プランが (クラスター化インデックス スキャンを使用して) あなたのクエリ プランと同じであることですが、クエリ コストの 9% をインデックス スキャンが占め、残りの 91% を並べ替えが占めています。テーブルに膨大な量のデータが含まれているか、ディスクが非常に遅いか、非常に遅いネットワーク接続上にあるとしか思えません。

于 2012-04-12T09:21:37.230 に答える
2

これはどのように可能ですか?er101_upd_date_iso 列にインデックスがない場合、クラスター化インデックス スキャンをどのように使用できますか?

インデックスは、各リーフ ノードが「行の束」(SQL 内部用語では「ページ」と呼ばれる) を指している B ツリーです。これは、インデックスが非クラスター化インデックスの場合です。

クラスタ化されたインデックスは特殊なケースであり、リーフ ノードが (それらを指すのではなく) 「行の束」を持っています。それが理由です...

1) テーブルには 1 つのクラスター化インデックスしか存在できません。

これは、テーブル全体がクラスター化インデックスとして格納されることも意味します。そのため、テーブル スキャンではなくインデックス スキャンが表示されるようになりました。

2) クラスター化インデックスを使用する操作は、一般に非クラスター化インデックスより高速です。

詳細については、http://msdn.microsoft.com/en-us/library/ms177443.aspx をご覧ください。

あなたが抱えている問題については、新しいインデックス(または既存のインデックスへの列)を追加すると INSERT/UPDATE コストが増加すると述べたので、この列をインデックスに追加することを実際に検討する必要があります。ただし、十分に活用されていないインデックス (または既存のインデックスの列) を削除して、「er101_upd_date_iso」に置き換えることができる場合があります。

インデックスの変更が不可能な場合は、列に統計を追加することをお勧めします。列にインデックス付きの列との相関関係がある場合は、問題を解決できます。

http://msdn.microsoft.com/en-us/library/ms188038.aspx

ところで、ER101_ACCT_ORDER_DTL のテーブル スキーマを投稿できれば、さらに多くの助けが得られます。そして既存のインデックスも...、おそらくそれらのいくつかを使用するようにクエリを書き直すことができます。

于 2012-04-11T07:09:19.347 に答える
2

一部のクエリで使用される一部の列にインデックスがある場合でも、「アドホック」クエリによってテーブル スキャンが発生するという事実は、このクエリを効率的に完了するのに十分なインデックスがないことを示しています。

特に日付範囲の場合、適切なインデックスを追加することは困難です。

クエリを見るだけで、データベースは最初の n レコードを返すことができるように、選択した列ですべてのレコードを並べ替える必要があります。

データベースは order by 句なしでフルテーブルスキャンも行いますか? テーブルには主キーがありますか? PK がないと、データベースはソートを実行するために一生懸命働かなければなりませんか?

于 2012-04-09T06:24:16.597 に答える
1

1M テストがより速く実行された理由の 1 つは、一時テーブルが完全にメモリ内にあり、サーバーでメモリ プレッシャーが発生した場合にのみディスクに移動する可能性があるためです。クエリを再作成して order by を削除するか、前述のように適切なクラスター化インデックスとカバー インデックスを追加するか、DMV にクエリを実行して IO プレッシャーをチェックし、ハードウェアが関連しているかどうかを確認することができます。

-- From Glen Barry
-- Clear Wait Stats (consider clearing and running wait stats query again after a few minutes)
-- DBCC SQLPERF('sys.dm_os_wait_stats', CLEAR);

-- Check Task Counts to get an initial idea what the problem might be

-- Avg Current Tasks Count, Avg Runnable Tasks Count, Avg Pending Disk IO Count across all schedulers
-- Run several times in quick succession
SELECT AVG(current_tasks_count) AS [Avg Task Count], 
       AVG(runnable_tasks_count) AS [Avg Runnable Task Count],
       AVG(pending_disk_io_count) AS [Avg Pending DiskIO Count]
FROM sys.dm_os_schedulers WITH (NOLOCK)
WHERE scheduler_id < 255 OPTION (RECOMPILE);

-- Sustained values above 10 suggest further investigation in that area
-- High current_tasks_count is often an indication of locking/blocking problems
-- High runnable_tasks_count is a good indication of CPU pressure
-- High pending_disk_io_count is an indication of I/O pressure
于 2012-04-10T23:26:56.067 に答える
0

インデックスを追加することはオプションではありませんが、それがテーブルスキャンを排除する唯一のオプションであると言ったことは知っています。スキャンを実行すると、SQL Server はテーブルの 200 万行すべてを読み取り、クエリを実行します。

この記事では詳細を説明していますが、覚えておいてください: Seek = 良い、Scan = 悪い。

次に、select * を削除して、必要な列だけを選択することはできませんか? 第三に、「where」節がない?インデックスがあっても、すべてを読んでいるので、インデックス スキャンが最適です (これはテーブル スキャンよりも優れていますが、シークではありません。これを目指す必要があります)。

于 2012-04-12T16:05:26.473 に答える