我有两张桌子:
"会话" - 它具有int密钥标识," session_id" - varchar," device_category" - varchar和其他一些colums。 有149239行。
Session_events" - 它有int键 身份," session_id" - uniqueidentifier和其他一些领域。 那里有3140768行。
此表已从非关系数据库导入 - Cassandra,因此我没有在MS SQL Server设计器中创建任何连接。但是,在session_id列上的Sessions和Session_events之间的真正连接是“多对多”
现在我要删除所有未在个人计算机" device_category"上发生的网络会话。所以我运行请求Delete * FROM sessions where device_category != "PC"
那很快。现在我想从Session_events表中删除所有不是PC会话。所以我运行请求
Delete FROM session_events where session_id Not In (SELECT distinct session_id FROM sessions)
该请求目前运行超过24小时,我不知道可以花多长时间......
(我有16 GB ram和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
答案 0 :(得分:4)
一次删除大量数据意味着数据库引擎必须在单个事务中完成所有这些操作。这意味着当你实际上不需要它时会产生巨大的开销(例如,你不需要回滚整个操作,或者你不关心一致性 - 你只想删除所有内容,如果它如果在中间失败,您只需再次运行查询以删除其余部分。
对于您的情况,您可以尝试批量删除。例如:
delete top 1000 from session_events where session_id Not In (SELECT distinct session_id FROM sessions)
重复直到表格为空。
另外,你从错误的角度出发。你可能最好先在两者之间创建一个外键,然后使用"删除级联"。这会自动删除不再具有有效session_events
的所有session
。如果你可以重新开始,可能明显更快。但是没有承诺:D
答案 1 :(得分:0)
为什么不使用左连接?另一种方法是使用EXISTS而不是IN:
DELETE FROM Session_events
WHERE NOT EXISTS(
SELECT 1
FROM Session
WHERE Session.Session_Id = Session_events.Session_Id
)
答案 2 :(得分:0)
有时删除的问题是等待获取所有相关行的锁定。尝试在循环中删除。
DECLARE @MyCursor CURSOR;
DECLARE @MyField YourFieldDataType;//replace with the data type of session_id
BEGIN
SET @MyCursor = CURSOR FOR
select session_id from session_events minus select session_id from sessions
OPEN @MyCursor
FETCH NEXT FROM @MyCursor
INTO @MyField
WHILE @@FETCH_STATUS = 0
BEGIN
delete session_events where session_id = @MyField
FETCH NEXT FROM @MyCursor
INTO @MyField
END;
CLOSE @MyCursor ;
DEALLOCATE @MyCursor;
END;
您还可以尝试将not in
重写为in
:
delete from session_events where session_id in (select session_id from session_events minus select session_id from sessions)
答案 3 :(得分:-1)
答案 4 :(得分:-2)
试试这段代码
delete e
from session_events e
left join sessions s (nolock)
on e.session_id = s.session_id
where s.session_id is null