通过超过60亿次操作来加速SQL查询

时间:2019-02-21 10:28:29

标签: sql postgresql

我们有一个存在以下问题的Django项目:

User对象存储在auth_user表中

这些对象与Profile对象具有一对一关系,该对象存储在yuza_profile表中。它与user的关系是通过user_id字段

维护的

但是,几年前,数千个Profile对象被删除而没有删除链接的User对象。

这些没有个人资料的用户正在我们的系统中引起问题,我们希望将其删除。

我创建了以下SQL查询来执行此任务

DELETE FROM auth_user WHERE id NOT IN (SELECT user_id FROM yuza_profile); 

Profile对象被删除以来,我无法扫描null字段上的*_id值-这是我在这里的第一步。

相反,我正在遍历两个表,两个表都包含60.000行以上,这导致查询速度缓慢且效率低下,超过60亿次操作(和服务器超时)

是否可以加快此查询的速度?我知道我的查询效率很低,但是我不知道有什么方法可以改善它,任何帮助将不胜感激。

编辑:根据要求,我添加了以下架构:

user_profile

id - integer
user_id - integer
gender - varchar(2)
birth_date - date
address - varchar(255)
city - varchar(255)
phone_number - varchar(10)
avatar - varchar(255)
---------------------
user_profile_pkey - (id)
user_profile_user_id_key - (user_id)
user_profile_user_id_fkey - (user_id) -> auth_user(id)
user_profile_pkey - (id) UNIQUE
user_profile_user_id_key - (user_id) UNIQUE
auth_user

id - integer
username - varchar(150)
first_name - varchar(30)
last_name - varchar(30)
email - varchar(75)
password - varchar(128)
is_staff - boolean
is_active - boolean
is_superuser - boolean
last_login - timestamp with time zone
date_joined - timestamp with time zone
---------------
auth_user_pkey - (id)
auth_user_username_key - (username)
auth_user_pkey - (id) UNIQUE
auth_user_username_key - (username) UNIQUE

我应该注意,我开始怀疑我使用的IDE(PycharmPro)是否可能是一个因素-使用SELECT语句测试查询时,IDE会将查询结果显示为每页500个结果的页面。最初的查询确实花费了不到一秒钟的时间-但是按下“转到最后一页”按钮花费了2分钟以上的时间(仅显示16000个结果)

2 个答案:

答案 0 :(得分:1)

我不太确定您的方法,我假设您采取了基于游标的策略,但您不能只是:

DELETE FROM auth_user WHERE id NOT IN (SELECT user_id FROM yuza_profile);

如果索引正确,则该DML指令将不需要那么多操作。

答案 1 :(得分:1)

我强烈建议您使用NOT EXISTS而不是NOT IN。它更直观地处理NULL值。 (如果子查询中的任何值为NOT IN,{NULL将过滤出所有行。)

因此,将查询写为:

DELETE au FROM auth_user au
    WHERE NOT EXISTS (SELECT 1
                      FROM yuza_profile vp 
                      WHERE vp.user_id = au.id
                     ); 

此查询可以利用yuza_profile(user_id)上的索引:

CREATE INDEX idx_yuza_profile_user_id ON yuza_profile(user_id);