sql - 极长的 "Not In"请求

标签 sql sql-server database performance query-performance

我有两个表:

  1. "Sessions"- 它有 int key identity, "session_id"- varchar, "device_category"- varchar 和其他一些列。 共有 149239 行。

  2. Session_events"- 它有 int key identity, "session_id"- uniqueidentifier 和其他一些字段。 那里有 3140768 行。

此表不是从关系数据库 Cassandra 导入的,所以我没有在 MS SQL Server 设计器中创建任何连接。但是 session_id 列上的 Session 和 Session_events 之间的真正联系是多对多

现在我想删除所有未在个人计算机“device_category”上发生的网络 session 。所以我运行请求 Delete * FROM sessions where device_category != "PC" 那很快。现在我想从 Session_events 表中删除所有非 PC session 。所以我运行请求

Delete FROM session_events where session_id Not In (SELECT distinct session_id FROM sessions)

该请求目前正在运行 24 小时以上,我不知道需要多长时间......

(我有 16 GB 内存和 Intel Xenon)。

我知道 Left Join 可以更快,但 20% 并不有趣。你看到更快完成我的任务的方法了吗?

----
CREATE TABLE [dbo].[session_events](
    [key] [bigint] IDENTITY(1,1) NOT NULL,
    [session_id] [uniqueidentifier](max) NULL,
    [visitor_id] [uniqueidentifier] NULL,
    [shipping_method] [varchar](max) NULL,
    [shipping_price] [varchar](max) NULL,
    [site_id] [int] NULL,
    [stream_data_chunk] [varbinary](max) NULL,
    [total] [varchar](max) NULL,
    [total_inc_tax] [varchar](max) NULL,
    [tracker_ver] [varchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE TABLE [dbo].[visitor_sessions](
    [key] [int] IDENTITY(1,1) NOT NULL,
    [visitor_id] [varchar](max) NULL,
    [created] [varchar](max) NULL,
    [session_id] [varchar](max) NULL
)

 CONSTRAINT [PK_visitor_sessions4] PRIMARY KEY CLUSTERED 
(
    [key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

最佳答案

一次删除大量数据意味着数据库引擎必须在单个事务中完成所有这些操作。这意味着当你实际上不需要它时会产生巨大的开销(例如,你不需要回滚整个操作,或者你不关心一致性 - 你只想删除所有内容,如果它在中间失败,你将再次运行查询以删除其余部分)。

对于您的情况,您可以尝试批量删除。例如:

delete top 1000 from session_events where session_id Not In (SELECT distinct session_id FROM sessions)

重复直到表格为空。

另外,你的出发点是错误的。您最好先在两者之间创建一个外键,然后使用“on delete cascade”。这将自动删除不再具有有效 session 的所有 session_events。如果您可以重新开始,它可能会快得多。没有 promise ,虽然 :D

关于sql - 极长的 "Not In"请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29621712/

相关文章:

sql - MSSQL : Finding all items between two dates

sql - 在 nvarchar 列中找到两个或更多相似字符

mysql - 加入投票表并对所有投票求和

sql - 我的查询选择中间行是否存在效率问题?

sql - 从同一 Azure SQL Server 上的其他数据库调用主数据库的函数

database - 使用 Neo4j 执行任意查询

mysql - 将新列作为外键添加到表中

mysql - 将表中的数据复制到另一个表 MySQL

mysql - 使用 SQL 和 JOIN 统计投票(这可能吗?)

sql - 为什么我的一年中的一周查询显示 "2022.52",而它应该显示 "2021.52"