sql-server – SQL Server INSERT进入巨大的表格很慢

前端之家收集整理的这篇文章主要介绍了sql-server – SQL Server INSERT进入巨大的表格很慢前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在sql Server 2008数据库中有一个大表,它有约5.7亿条记录.
每天我们运行一个批处理作业,该文件需要一个20万个左右的事务记录的文件,并且对这个数据进行分组和总结并将其插入到大表中.

最近我已经尝试将大型表的聚簇索引改为一个标识int列,这样就将插入从3小时缩短到了一小时,但是我仍然感到困惑,为什么这个简单的查询应该花费这么长时间才能运行(不管桌子的大小)

这是有5.7亿行的表

  1. CREATE TABLE [dbo].[POINTS_EARNED](
  2. [POINTS_EARNED_ID]int identity not null,[CARD_ID] [int] NOT NULL,[CYCLE_ID] [int] NOT NULL,[POINTS_CODE] [int] NOT NULL,[NO_POINTS] [int] NULL,[ACCOUNT_ID] [int] NOT NULL,[CREATED_DATE] [datetime] NULL,[CREATED_BY] [varchar](20) NULL,[LAST_MODIFIED_DATE] [datetime] NULL,[LAST_MODIFIED_BY] [varchar](20) NULL,[DELETED] [bit] NULL,CONSTRAINT [PK_POINTS_EARNED] PRIMARY KEY CLUSTERED
  3. (
  4. [POINTS_EARNED_ID] ASC
  5. )WITH (PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  6.  
  7. ) ON [PRIMARY]

它还有一些约束(默认值和外键)和索引,我想知道这些是什么导致问题.

运行一小时的实际sql是:

  1. insert into points_earned (
  2. card_id,cycle_id,points_code,no_points,account_id
  3. )
  4.  
  5. select pe.card_id,pe.cycle_id,pe.points_code,sum(pe.no_points),pe.account_id
  6. from #points_earned pe
  7. group by pe.card_id,pe.account_id

临时表#points_earned具有约20万行,具有以下结构(无索引)

  1. create table #points_earned (
  2. card_id int,cycle_id int,points_code int,card_type varchar(5),no_points int,account_id int
  3. )

所以,我想就是否应该提出一些意见

>在临时表中添加索引
>在添加数据之前,在大表上删除非聚簇索引,然后重新创建它们
>任何其他选项?

更新 – 根据要求更多信息
– select语句在2秒内运行而不插入,所以这似乎不是问题,所以可能不需要担心索引临时表

索引,(更新)触发器和约束是:

  1. CREATE NONCLUSTERED INDEX [IDX_CYCLE_ID] ON [dbo].[POINTS_EARNED]
  2. (
  3. [CYCLE_ID] ASC
  4. )WITH (PAD_INDEX = OFF,SORT_IN_TEMPDB = OFF,DROP_EXISTING = OFF,ONLINE = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  5. GO
  6. CREATE NONCLUSTERED INDEX [IX_ACCOUNT_ID] ON [dbo].[POINTS_EARNED]
  7. (
  8. [ACCOUNT_ID] ASC
  9. )WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  10. GO
  11. CREATE NONCLUSTERED INDEX [IX_ACCOUNT_ID_POINTS_CODE] ON [dbo].[POINTS_EARNED]
  12. (
  13. [ACCOUNT_ID] ASC,[POINTS_CODE] ASC
  14. )
  15. INCLUDE ( [CARD_ID],[CYCLE_ID],[NO_POINTS]) WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  16. GO
  17. CREATE NONCLUSTERED INDEX [RELATION_151_FK] ON [dbo].[POINTS_EARNED]
  18. (
  19. [CARD_ID] ASC,[CYCLE_ID] ASC
  20. )WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  21. GO
  22. CREATE NONCLUSTERED INDEX [RELATION_152_FK] ON [dbo].[POINTS_EARNED]
  23. (
  24. [POINTS_CODE] ASC
  25. )WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  26. GO
  27. /****** Object: Trigger [update_points_earned] Script Date: 09/13/2013 13:20:54 ******/
  28. SET ANSI_NULLS ON
  29. GO
  30. SET QUOTED_IDENTIFIER ON
  31. GO
  32. CREATE TRIGGER [dbo].[update_points_earned] ON [dbo].[POINTS_EARNED]
  33. FOR UPDATE
  34. AS
  35. BEGIN
  36. UPDATE points_earned
  37. SET Last_Modified_By = USER,Last_Modified_Date = GETDATE()
  38. FROM
  39. points_earned t,inserted i
  40. WHERE
  41. t.card_id = i.card_id AND
  42. t.cycle_id = i.cycle_id AND
  43. t.points_code = i.points_code AND
  44. t.account_id = i.account_id
  45. END
  46. GO
  47. /****** Object: Default [DF_POINTS_EARNED_ACCOUNT_ID] Script Date: 09/13/2013 13:20:54 ******/
  48. ALTER TABLE [dbo].[POINTS_EARNED] ADD CONSTRAINT [DF_POINTS_EARNED_ACCOUNT_ID] DEFAULT ((0)) FOR [ACCOUNT_ID]
  49. GO
  50. /****** Object: Default [DF_POINTS_EARNED_CREATED_DATE] Script Date: 09/13/2013 13:20:54 ******/
  51. ALTER TABLE [dbo].[POINTS_EARNED] ADD CONSTRAINT [DF_POINTS_EARNED_CREATED_DATE] DEFAULT (getdate()) FOR [CREATED_DATE]
  52. GO
  53. /****** Object: Default [DF_POINTS_EARNED_CREATED_BY] Script Date: 09/13/2013 13:20:54 ******/
  54. ALTER TABLE [dbo].[POINTS_EARNED] ADD CONSTRAINT [DF_POINTS_EARNED_CREATED_BY] DEFAULT (user_name()) FOR [CREATED_BY]
  55. GO
  56. /****** Object: Default [DF_POINTS_EARNED_DELETED] Script Date: 09/13/2013 13:20:54 ******/
  57. ALTER TABLE [dbo].[POINTS_EARNED] ADD CONSTRAINT [DF_POINTS_EARNED_DELETED] DEFAULT ((0)) FOR [DELETED]
  58. GO
  59. /****** Object: ForeignKey [FK_POINTS_E_REFERENCE_CYCLE_CA] Script Date: 09/13/2013 13:20:54 ******/
  60. ALTER TABLE [dbo].[POINTS_EARNED] WITH CHECK ADD CONSTRAINT [FK_POINTS_E_REFERENCE_CYCLE_CA] FOREIGN KEY([CARD_ID],[CYCLE_ID])
  61. REFERENCES [dbo].[CYCLE_CARD] ([CARD_ID],[CYCLE_ID])
  62. GO
  63. ALTER TABLE [dbo].[POINTS_EARNED] CHECK CONSTRAINT [FK_POINTS_E_REFERENCE_CYCLE_CA]
  64. GO
  65. /****** Object: ForeignKey [FK_POINTS_E_REFERENCE_POINTS_C] Script Date: 09/13/2013 13:20:54 ******/
  66. ALTER TABLE [dbo].[POINTS_EARNED] WITH NOCHECK ADD CONSTRAINT [FK_POINTS_E_REFERENCE_POINTS_C] FOREIGN KEY([POINTS_CODE])
  67. REFERENCES [dbo].[POINTS_CODE] ([POINTS_CODE])
  68. GO
  69. ALTER TABLE [dbo].[POINTS_EARNED] CHECK CONSTRAINT [FK_POINTS_E_REFERENCE_POINTS_C]
  70. GO
  71. /****** Object: ForeignKey [FK_POINTS_EARNED_REF_ACCOUNT] Script Date: 09/13/2013 13:20:54 ******/
  72. ALTER TABLE [dbo].[POINTS_EARNED] WITH NOCHECK ADD CONSTRAINT [FK_POINTS_EARNED_REF_ACCOUNT] FOREIGN KEY([ACCOUNT_ID])
  73. REFERENCES [dbo].[ACCOUNT] ([ACCOUNT_ID])
  74. GO
  75. ALTER TABLE [dbo].[POINTS_EARNED] CHECK CONSTRAINT [FK_POINTS_EARNED_REF_ACCOUNT]

编辑2,查询计划的insert语句

  1. |--Sequence
  2. |--Index Insert(OBJECT:([Progressive_Points].[dbo].[POINTS_EARNED].[IDX_CYCLE_ID]),SET:([POINTS_EARNED_ID1040] = [Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID],[CYCLE_ID1041] = [Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID]) WITH ORDERED PREFETCH)
  3. | |--Sort(ORDER BY:([Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID] ASC,[Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID] ASC))
  4. | |--Table Spool
  5. | |--Clustered Index Insert(OBJECT:([Progressive_Points].[dbo].[POINTS_EARNED].[PK_POINTS_EARNED]),SET:([Progressive_Points].[dbo].[POINTS_EARNED].[CARD_ID] = RaiseIfNullInsert([tempdb].[dbo].[#points_earned].[card_id] as [pe].[card_id]),[Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID] = RaiseIfNullInsert([tempdb].[dbo].[#points_earned].[cycle_id] as [pe].[cycle_id]),[Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_CODE] = RaiseIfNullInsert([tempdb].[dbo].[#points_earned].[points_code] as [pe].[points_code]),[Progressive_Points].[dbo].[POINTS_EARNED].[NO_POINTS] = [Expr1006],[Progressive_Points].[dbo].[POINTS_EARNED].[ACCOUNT_ID] = RaiseIfNullInsert([tempdb].[dbo].[#points_earned].[account_id] as [pe].[account_id]),[Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID] = [Expr1007],[Progressive_Points].[dbo].[POINTS_EARNED].[CREATED_DATE] = [Expr1008],[Progressive_Points].[dbo].[POINTS_EARNED].[CREATED_BY] = [Expr1009],[Progressive_Points].[dbo].[POINTS_EARNED].[DELETED] = [Expr1010],[Progressive_Points].[dbo].[POINTS_EARNED].[LAST_MODIFIED_DATE] = NULL,[Progressive_Points].[dbo].[POINTS_EARNED].[LAST_MODIFIED_BY] = NULL) WITH UNORDERED PREFETCH)
  6. | |--Compute Scalar(DEFINE:([Expr1008]=getdate(),[Expr1009]=CONVERT_IMPLICIT(varchar(20),user_name(),0),[Expr1010]=(0)))
  7. | |--Compute Scalar(DEFINE:([Expr1007]=getidentity((1243867498),(8),NULL)))
  8. | |--Top(ROWCOUNT est 0)
  9. | |--Parallelism(Gather Streams)
  10. | |--Compute Scalar(DEFINE:([Expr1006]=CASE WHEN [Expr1062]=(0) THEN NULL ELSE [Expr1063] END))
  11. | |--Hash Match(Aggregate,HASH:([pe].[card_id],[pe].[cycle_id],[pe].[points_code],[pe].[account_id]),RESIDUAL:([tempdb].[dbo].[#points_earned].[card_id] as [pe].[card_id] = [tempdb].[dbo].[#points_earned].[card_id] as [pe].[card_id] AND [tempdb].[dbo].[#points_earned].[cycle_id] as [pe].[cycle_id] = [tempdb].[dbo].[#points_earned].[cycle_id] as [pe].[cycle_id] AND [tempdb].[dbo].[#points_earned].[points_code] as [pe].[points_code] = [tempdb].[dbo].[#points_earned].[points_code] as [pe].[points_code] AND [tempdb].[dbo].[#points_earned].[account_id] as [pe].[account_id] = [tempdb].[dbo].[#points_earned].[account_id] as [pe].[account_id]) DEFINE:([Expr1062]=COUNT_BIG([tempdb].[dbo].[#points_earned].[no_points] as [pe].[no_points]),[Expr1063]=SUM([tempdb].[dbo].[#points_earned].[no_points] as [pe].[no_points])))
  12. | |--Parallelism(Repartition Streams,Hash Partitioning,PARTITION COLUMNS:([pe].[card_id],[pe].[account_id]))
  13. | |--Clustered Index Scan(OBJECT:([tempdb].[dbo].[#points_earned] AS [pe]))
  14. |--Index Insert(OBJECT:([Progressive_Points].[dbo].[POINTS_EARNED].[IX_ACCOUNT_ID]),SET:([POINTS_EARNED_ID1042] = [Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID],[ACCOUNT_ID1043] = [Progressive_Points].[dbo].[POINTS_EARNED].[ACCOUNT_ID]) WITH ORDERED PREFETCH)
  15. | |--Sort(ORDER BY:([Progressive_Points].[dbo].[POINTS_EARNED].[ACCOUNT_ID] ASC,[Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID] ASC))
  16. | |--Table Spool
  17. |--Assert(WHERE:(CASE WHEN [Expr1050] IS NULL THEN (0) ELSE NULL END))
  18. | |--Nested Loops(Left Semi Join,OUTER REFERENCES:([Progressive_Points].[dbo].[POINTS_EARNED].[ACCOUNT_ID],[Expr1068]) WITH UNORDERED PREFETCH,DEFINE:([Expr1050] = [PROBE VALUE]))
  19. | |--Index Insert(OBJECT:([Progressive_Points].[dbo].[POINTS_EARNED].[IX_ACCOUNT_ID_POINTS_CODE]),SET:([POINTS_EARNED_ID1044] = [Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID],[CARD_ID1045] = [Progressive_Points].[dbo].[POINTS_EARNED].[CARD_ID],[CYCLE_ID1046] = [Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID],[POINTS_CODE1047] = [Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_CODE],[NO_POINTS1048] = [Progressive_Points].[dbo].[POINTS_EARNED].[NO_POINTS],[ACCOUNT_ID1049] = [Progressive_Points].[dbo].[POINTS_EARNED].[ACCOUNT_ID]) WITH UNORDERED PREFETCH)
  20. | | |--Table Spool
  21. | |--Clustered Index Seek(OBJECT:([Progressive_Points].[dbo].[ACCOUNT].[PK_ACCOUNT]),SEEK:([Progressive_Points].[dbo].[ACCOUNT].[ACCOUNT_ID]=[Progressive_Points].[dbo].[POINTS_EARNED].[ACCOUNT_ID]) ORDERED FORWARD)
  22. |--Assert(WHERE:(CASE WHEN [Expr1054] IS NULL THEN (0) ELSE NULL END))
  23. | |--Nested Loops(Left Semi Join,OUTER REFERENCES:([Progressive_Points].[dbo].[POINTS_EARNED].[CARD_ID],[Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID],[Expr1070]) WITH UNORDERED PREFETCH,DEFINE:([Expr1054] = [PROBE VALUE]))
  24. | |--Index Insert(OBJECT:([Progressive_Points].[dbo].[POINTS_EARNED].[RELATION_151_FK]),SET:([POINTS_EARNED_ID1051] = [Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID],[CARD_ID1052] = [Progressive_Points].[dbo].[POINTS_EARNED].[CARD_ID],[CYCLE_ID1053] = [Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID]) WITH ORDERED PREFETCH)
  25. | | |--Sort(ORDER BY:([Progressive_Points].[dbo].[POINTS_EARNED].[CARD_ID] ASC,[Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID] ASC,[Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID] ASC))
  26. | | |--Table Spool
  27. | |--Row Count Spool
  28. | |--Index Seek(OBJECT:([Progressive_Points].[dbo].[CYCLE_CARD].[IDX_NCLST_CARD_ID_CYCLE_ID]),SEEK:([Progressive_Points].[dbo].[CYCLE_CARD].[CARD_ID]=[Progressive_Points].[dbo].[POINTS_EARNED].[CARD_ID] AND [Progressive_Points].[dbo].[CYCLE_CARD].[CYCLE_ID]=[Progressive_Points].[dbo].[POINTS_EARNED].[CYCLE_ID]) ORDERED FORWARD)
  29. |--Assert(WHERE:(CASE WHEN [Expr1057] IS NULL THEN (0) ELSE NULL END))
  30. |--Merge Join(Left Semi Join,MANY-TO-MANY MERGE:([Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_CODE])=([Progressive_Points].[dbo].[POINTS_CODE].[POINTS_CODE]),RESIDUAL:([Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_CODE]=[Progressive_Points].[dbo].[POINTS_CODE].[POINTS_CODE]))
  31. |--Index Insert(OBJECT:([Progressive_Points].[dbo].[POINTS_EARNED].[RELATION_152_FK]),SET:([POINTS_EARNED_ID1055] = [Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID],[POINTS_CODE1056] = [Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_CODE]) WITH ORDERED PREFETCH)
  32. | |--Sort(ORDER BY:([Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_CODE] ASC,[Progressive_Points].[dbo].[POINTS_EARNED].[POINTS_EARNED_ID] ASC))
  33. | |--Table Spool
  34. |--Index Scan(OBJECT:([Progressive_Points].[dbo].[POINTS_CODE].[POINTS_CODES_PK]),ORDERED FORWARD)

解决方法

好的,这是我会做的:

>检查是否需要两个索引[IX_ACCOUNT_ID_POINTS_CODE]和[IX_ACCOUNT_ID],因为它们可能是冗余的.
>在执行INSERT之前,禁用触发器并删除外键.
> INSERT设置通常由Trigger设置的字段,并确保FK列的值有效.
>重新启用触发器,并重新创建带有NOCHECK的外键.

我将离开索引,因为您插入的总行数不到0.2%,所以可能更快地更新它们就地而不是删除和重建它们.

猜你在找的MsSQL相关文章