Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
加速SQL子查询_Sql_Postgresql_Performance_Subquery - Fatal编程技术网

加速SQL子查询

加速SQL子查询,sql,postgresql,performance,subquery,Sql,Postgresql,Performance,Subquery,我正在开发一个系统,任何数量的公司都可以将中小型企业信息上传到数据库并进行搜索 表import\u data存储不同公司上传的SME信息。 每个公司上传的信息由表import\u data的company\u id列标识 CREATE TABLE import_data ( id uuid NOT NULL, # Indexed company_id integer NOT NULL, # Indexed business_name character va

我正在开发一个系统,任何数量的公司都可以将中小型企业信息上传到数据库并进行搜索

import\u data
存储不同公司上传的SME信息。 每个公司上传的信息由表
import\u data
company\u id
列标识

CREATE TABLE import_data 
(
    id uuid NOT NULL,    # Indexed
    company_id integer NOT NULL,    # Indexed
    business_name character varying,    # Indexed
    no_of_rating double precision,    # Indexed
    no_of_reviews double precision,    # Indexed
    phone character varying,    # Indexed
    email character varying,    # Indexed
    address character varying,    # Indexed
    upserted_by integer,  # Not indexed
    upsert_date timestamp without time zone,    # Not indexed
)
PARTITION BY LIST (company_id);
现在我正在开发一个推荐系统,将一个电话号码不存在于某家公司上传的数据中,但存在于另一家公司上传的数据中的记录推荐给第一家公司购买。 公司与其拥有的所有导入数据记录之间的关系存储在另一个表中
import\u data\u company\u rel
。此表包括特定公司上载和购买的所有
import\u数据
记录

CREATE TABLE import_data_company_rel 
(
    record_id uuid NOT NULL,    # Indexed
    company_id integer NOT NULL    # Indexed
)
PARTITION BY LIST (company_id);
这两个表都是分区的,这样每个公司都将在自己的分区中存储数据

例如,id为1的公司将在import_data_1、import_data_company_rel_1中存储其数据,id为2的公司将在import_data_2中存储其数据,import_data_company_rel_2具有相同的表import_data和import_data_company_rel模式

这是一个SQL查询,用于获取特定公司的推荐记录,比如id为1

SELECT id,business_name,address
FROM import_data 
INNER JOIN import_data_company_rel idcr ON import_data.id = idcr.record_id
WHERE idcr.company_id != 1 
  AND import_data.phone NOT IN (SELECT import_data.phone 
                                FROM import_data 
                                INNER JOIN import_data_company_rel idcr
                                      ON import_data.id = idcr.record_id 
                                WHERE idcr.company_id = 1)
LIMIT 100 OFFSET 0;
此查询获取第一页推荐结果,电话记录不包括在公司1的记录中

尽管这对少量记录有效,但此查询不能很好地随记录数扩展

当记录的数量以百万计时,它甚至在一个小时后仅仅获取100条记录都不会完成执行

我发现查询中减慢执行速度的部分是子查询

SELECT import_data.phone 
FROM import_data 
INNER JOIN import_data_company_rel idcr
      ON import_data.id = idcr.record_id 
WHERE idcr.company_id = 1
它将选择id为1的公司已拥有的所有电话号码,以便从建议中筛选。此查询将逐行扫描整个表

我不认为对表进行分区与慢查询有任何关系,因为即使没有分区,查询也很慢

explain (analyze, buffers, format text)
结果可在以下位置看到。 我正在开发postgesql v13.2


如何加快查询速度?有可能吗?感谢您的帮助。谢谢。

您可以做两件事来提高性能:

  • 通过以下方式提高仅索引扫描的速度

    VACUUM import_data_company_rel_1;
    
    这将消除昂贵的堆获取

  • 重写查询以使用
    不存在

    import_data.phone NOT IN
        (SELECT import_data.phone
         FROM import_data
            INNER JOIN import_data_company_rel idcr
               ON import_data.id = idcr.record_id
         WHERE idcr.company_id = 1)
    
    可以重写为

    NOT EXISTS
        (SELECT 1
         FROM import_data
            INNER JOIN import_data_company_rel idcr
               ON import_data.id = idcr.record_id
         WHERE idcr.company_id = 1
           AND import_data.phone = import_data.phone)
    

  • 它是不存在还是存在?询问b/c我没有得到关于不存在的结果。并且在上存在一些结果。它应该是
    不存在
    。这两句话的意思是一样的:“这张唱片不在我的财产范围内”和“我不拥有任何与这张唱片相等的东西”。真空有助于完成死刑。我在一个新的数据库中使用NOT EXISTS子句进行测试。我不知道我是否做错了什么,或者连接同一个表import_数据时有什么问题,notexists似乎不起作用。以下是我尝试插入导入数据(公司id、id、电话)值(1,'b9c9d29b-cedf-45d8-afb4-92d67de0e021','1111111'),(1,'d335e5ae-b172-4372-af5a-b26f5715fc9b','2222');将值(1,'d335e5ae-b172-4372-af5a-b26f5715fc9b'),(1,'b9c9d29b-cedf-45d8-afb4-92d67de0e021')插入导入数据公司关系(公司id,记录id)现在模拟公司2购买记录<代码>插入导入数据公司关系(公司id,记录id)值(2,'b9c9d29b-cedf-45d8-afb4-92d67de0e021')但是查询没有给出结果。然后我发现这件衣服是这样的。有没有办法将查询的结果与子查询的结果连接起来?好吧,因为您有一个
    限制100
    ,所以您可能可以将
    不在
    中,而不重写查询。