SQL查询有30条记录的表

SQL查询有30条记录的表,sql,sql-server-2014,Sql,Sql Server 2014,我在本地SQL Server中构建表时遇到问题。最初它导致tempdb表变满并引发异常。这有很多联接和外部应用程序,因此为了找到问题的具体位置,我在sql查询中对第一个表进行了选择,以确定所用的时间,这很快,因此我随后添加了下一个表,即查询中的第一个联接并重新运行,我继续执行此操作,直到找到停止的表 我发现问题(或者至少是第一个问题)在于shipper_container表。这个表是巨大的,单独拉动它会得到一个System.OutOfMemoryException,它只在该表的结果上显示一个se

我在本地SQL Server中构建表时遇到问题。最初它导致tempdb表变满并引发异常。这有很多联接和外部应用程序,因此为了找到问题的具体位置,我在sql查询中对第一个表进行了选择,以确定所用的时间,这很快,因此我随后添加了下一个表,即查询中的第一个联接并重新运行,我继续执行此操作,直到找到停止的表

我发现问题(或者至少是第一个问题)在于shipper_container表。这个表是巨大的,单独拉动它会得到一个System.OutOfMemoryException,它只在该表的结果上显示一个select(它只有5列)。它减少了1600万条记录,但有3000万行。它的大小为1.2GB。这对我来说似乎不是太大,以至于SQL Management studio无法处理它

使用WHERE语句收集2015年1月1日至1月10日之间的值仍然导致搜索耗时超过5分钟,并且在我取消时仍在执行。我还为每个select参数添加了索引,这也没有提高性能

下面是SQL查询。您可以看到,我已经注释掉了尚未添加到其他联接和外部应用中的其他参数

DECLARE @startDate DATETIME
DECLARE @endDate DATETIME
DECLARE @Shipper_Key INT = NULL
DECLARE @Part_Key INT = NULL

SET @startDate = '2015-01-01'
SET @endDate = '2015-01-10'

SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

INSERT Shipped_Container
(
    Ship_Date,  
    Invoice_Quantity,
    Shipper_No,
    Serial_No,
    Truck_Key,
    Shipper_Key
)
SELECT
    S.Ship_Date,
    SC.Quantity,
    S.Shipper_No,
    SC.Serial_No, 
    S.Truck_Key,
    S.Shipper_Key
    FROM Shipper AS S
JOIN Shipper_Line AS SL
    --ON SL.PCN = S.PCN
    ON SL.Shipper_Key = S.Shipper_Key
JOIN Shipper_Container AS SC
    --ON SC.PCN = SL.PCN
    ON SC.Shipper_Line_Key = SL.Shipper_Line_Key
WHERE S.Ship_Date >= @startDate AND S.Ship_Date <= @endDate
    AND S.Shipper_Key = ISNULL(@Shipper_Key, S.Shipper_Key)
    AND SL.Part_Key = ISNULL(@Part_Key, SL.Part_Key)
DECLARE@startDate-DATETIME
声明@endDate-DATETIME
声明@Shipper_Key INT=NULL
声明@Part_Key INT=NULL
SET@startDate='2015-01-01'
设置@endDate='2015-01-10'
不计数;
将事务隔离级别设置为“读取未提交”;
插入已装运的集装箱
(
装船日期,
发票数量,
托运人:不,
序号:,
卡车钥匙,
托运人钥匙
)
挑选
美国船日,
SC.数量,
美国运货人(u No),
SC.序列号,
美国卡车协会,
S.U键
从托运人处
以SL的身份加入Shipper_行
--关于SL.PCN=S.PCN
在SL.Shipper_Key=S.Shipper_Key上
加入托运人/集装箱作为SC
--在SC.PCN=SL.PCN上
在SC.Shipper\u Line\u Key=SL.Shipper\u Line\u Key上

其中S.Ship_Date>=@startDate和S.Ship_Date不执行a
选择。。。返回时从SS Management Studio中的yourtable
成百上千万的人吵架。当系统必须在ManagementStudio数据表的屏幕上绘制并显示1GB数据时,数据量会大得多

服务器实例在本地网络上运行

执行
操作时,请选择。。。从SSMS中的yourtable
,服务器必须将所有数据发送到您的笔记本电脑/台式机。这在网络上是相当多的不必要的压力。 插入时不应该出现问题,因为所有内容都保留在服务器上。但是,如果您的数据模型不够好,留在服务器上并不意味着速度会很快

将事务隔离级别设置为“读取未提交”

你可能会得到肮脏的数据,如果你使用。。。除非你知道它为什么在那里,为什么你需要它,否则最好把它拿走

我还为每个select参数添加了索引,这也没有提高性能

如果您的意思是索引:

  • 美国船日
  • SC.数量
  • 美国运货人(u No)
  • SC.序列号
  • 美国卡车协会
  • S.U键
它们的定义是什么? 如果它们是1列上的单个索引,则可以删除SC.Quantity、S.Shipper\u No、SC.Serial\u No和S.Truck\u Key上的索引。它们没有被使用。 发货日期和发货人密钥可能有用。这完全取决于您的模型和现有主键。(您需要对其进行描述,请参见下文)

如果您能告诉我们:

  • 三个表之间的关系(哪个字段链接A到B以及在哪个方向)
  • 3个表上的主键
  • 3个表中所有索引(和列)的完整列表
如果没有一个索引是有用的,或者缺少索引,它很可能会读取整个3个表并尝试匹配它们。因为它相当大,所以没有足够的内存来处理它,它使用tempdb来存储中间数据

现在我假设shipper_key+PCN是每个表上的主键。 我想你可以试试:

  • 您可以在S.Ship_日期创建索引

    Create Index Shipper_Line_Ship_Date(Ship_Date) -- subject to updates according to your Primary Key
    
  • 查询优化器不能将索引(如果存在)与以下where子句一起使用:

    AND S.Shipper_Key = ISNULL(@Shipper_Key, S.Shipper_Key)
    AND SL.Part_Key = ISNULL(@Part_Key, SL.Part_Key)
    
    您可以使用:

    AND (S.Shipper_Key = @Shipper_Key or @Shipper_Key is null)
    AND (SL.Part_Key = @Part_Key or @Part_Keyis null)
    
  • 在U键和PCN上建立索引会有所帮助

最后

如上所述,我们需要更多地了解您的数据模型(创建表…),主键和索引(创建索引)。您可以在这里创建一个modele,其中包含所有3个create表及其索引。然后转到链接并在此处添加链接

在SSMS中,您可以右键单击一个表,转到
脚本表为/Create to/New Query Window
,并将其添加到此处或中。只保留
CREATE TABLE…
部分到第一个
GO
。 然后可以对所有索引执行相同的操作

还应添加查询计划的副本。
在SSMS中,进入
查询菜单/显示估计的执行计划
并右键单击以将其保存为xml(xml更好)。它只是一个估计,不会执行整个查询。应该很快。

发布执行计划是一件好事。您可以从SQLServerManagementStudio以XML格式导出,这对于大多数人来说是最容易使用的,而不是发布带有计划的图片。另外,让我们知道表中的索引(及其类型)也会有所帮助。