优化超过 200,000 条记录的查询

Posted

技术标签:

【中文标题】优化超过 200,000 条记录的查询【英文标题】:optimize query over more than 200,000 records 【发布时间】:2014-02-14 09:25:52 【问题描述】:

我正在处理一个现有项目,一切正常,但现在该网站包含超过 200,000 条记录。现在我遇到了性能问题。现在,当我尝试从表中获取记录时,即使我在查询中使用了分页,也需要 20 多分钟才能获取记录。下面是我使用左连接从多个表中获取记录的查询。

    SELECT cus.sl_no, cus.customer_name, ccd.address, ccd.mobile_no, ccd.residence_no,
           ccd.office_no,id.customer_id,cid.manufacturer,cid.model,cid.model_year,
           cid.vin_no,cid.renewal_insurance_date,cid.insurance_company,
           cid.cr_no,cid.inhouse_outside,cid.sales_consultant_name,
           cid.sales_consultant_contact_no,cid.insurance_date,
           cid.vehicle_registration_no    
    FROM customer_insurance_details cid 
    LEFT JOIN call_allotment_ref_admin admin 
         ON cid.customer_id = admin.customer_id 
    LEFT JOIN customer as cus 
         ON cid.customer_id = cus.customer_id 
    LEFT JOIN customer_contact_details as ccd 
         ON cid.customer_id = ccd.customer_id 
    WHERE admin.alloted_date IS NULL 
      AND cid.manufacturer='"+mf+"' 
      AND cid.renewal_insurance_date = '"+mnth+"' 
    limit "+pageNo+",100

此查询根据 customer_insurance_details 中的制造商和月份从客户、customer_insurance_details 和 customer_contact_details 中获取记录和 加入客户和 customer_contact_details。

还有一个表 call_allotment_ref_admin,在两个表 cutomer_insurance_details/call_allotment_ref_admin 中都有共同的 customer_id,现在当我运行查询时 call_allotment_ref_admin 中的客户不应该在 customer_insurance_details 中可见。

如果 call_allotment_ref_admin 和 customer_insurance_details 中有 101 customer_id,那么当我将获取记录时,该客户不应该是可见的。

这是一个现有项目,我不允许在表中添加或删除任何列,我只需要优化查询并加快结果获取速度。

如果您能提供一些这方面的信息,我将非常感激。

客户

    sl_noint(10) NOT NULL
    customer_idvarchar(20) NOT NULL
    customer_namevarchar(100) NULL
    create_timedatetime NOT NULL
    last_update_timedatetime NOT NULL

Customer_contact_details

    sl_noint(10) NOT NULL
    customer_idvarchar(20) NOT NULL
    addressvarchar(400) NULL
    cityvarchar(50) NULL
    statevarchar(50) NULL
    pin_codevarchar(15) NULL
    countryvarchar(50) NULL
    emailvarchar(200) NULL
    mobile_novarchar(100) NULL
    residence_novarchar(100) NULL
    office_novarchar(100) NULL
    create_timedatetime NOT NULL
    last_update_timedatetime NOT NULL
    vehicle_classvarchar(50) NULL
    seating_capacityvarchar(50) NULL
    new_emailvarchar(100) NULL
    new_numbervarchar(50) NULL
    cubic_capacityvarchar(50) NULL
    special_conditionvarchar(200) NULL
    lastyear_premiumvarchar(50) NULL

Customer_insurance_details

    sl_noint(10) NOT NULL
    customer_idvarchar(20) NOT NULL
    vin_novarchar(50) NOT NULL
    insurance_datevarchar(30) NULL
    renewal_insurance_datevarchar(30) NULL
    insurance_companyvarchar(100) NULL
    service_adviser_idvarchar(100) NULL
    idv_novarchar(50) NULL
    premiumvarchar(50) NULL
    claim_bonusvarchar(50) NULL
    create_timedatetime NOT NULL
    last_update_timedatetime NOT NULL
    sales_consultant_namevarchar(100) NULL
    sales_consultant_contact_novarchar(50) NULL
    customer_typevarchar(50) NOT NULL
    vehicle_registration_novarchar(50) NULL
    manufacturervarchar(50) NULL
    modelvarchar(200) NULL
    model_yearvarchar(30) NULL
    cr_novarchar(50) NULL
    inhouse_outsidevarchar(50) NULL
    cover_note_novarchar(50) NULL
    variantvarchar(50) NULL
    call_statusvarchar(50) NULL
    service_advisor_namevarchar(70) NULL
    service_advisor_contact_novarchar(50) NULL
    accessories_typevarchar(50) NULL
    accessories_valuevarchar(50) NULL

call_allotment_ref_admin

    sl_noint(50) NOT NULL
    user_idvarchar(100) NULL
    permission_levelvarchar(50) NULL
    managerIdvarchar(100) NULL
    customer_idvarchar(100) NULL
    call_statusvarchar(70) NULL
    alloted_datedate NULL
    insurance_datevarchar(30) NULL
    customer_namevarchar(100) NULL
    addressvarchar(200) NULL
    mobile_novarchar(50) NULL
    residence_novarchar(50) NULL
    office_novarchar(50) NULL
    manufacturervarchar(70) NULL
    modelvarchar(200) NULL
    model_yearvarchar(30) NULL
    vin_novarchar(100) NULL
    insurance_companyvarchar(100) NULL
    cr_novarchar(100) NULL
    sales_consultant_namevarchar(100) NULL
    sales_consultant_contact_novarchar(50) NULL
    inhouse_outsidevarchar(50) NULL
    create_timedatetime NULL
    last_update_timedatetime NULL
    alloted_call_idvarchar(50) NULL
    ins_monthvarchar(50) NULL

【问题讨论】:

您的“customer_insurance_details”表上是否有任何索引。如果不允许,您是否可以创建索引? 不,还没有创建任何索引,是的,我可以创建索引 我注意到,当我不加入customer和customer_contact_details时,我很快就得到了结果。 在这些连接列上放置索引,为什么它们是 varchar?假设这些列中有数字,int 会更快。 【参考方案1】:

使用下面列出的指南,您可以在主表上创建索引,在这种情况下为“customer_insurance_details”。这应该可以帮助您减少查询的运行时间。因此,您的查询在某种意义上进行了优化,因为它不使用任何聚合函数并直接基于少量 JOINS 获取列。所以我觉得索引是你唯一的选择。

您应该为经常使用的列创建索引 WHERE 子句。 您应该在使用的列上创建索引 经常加入表格。 您应该在列上创建索引 在 ORDER BY 子句中经常使用。 您应该在 具有少数相同值或唯一值的列 桌子。 不应在小表(使用 只有几个块),因为全表扫描可能比 索引查询。 如果可能,请选择对行进行排序的主键 以最合适的顺序。 如果连接的只有一列 索引在 WHERE 子句中经常使用,将该列放在第一个 CREATE INDEX 语句。 如果串联中的列多于一列 索引在 WHERE 子句中经常使用,放置最有选择性的 CREATE INDEX 语句中的第一个列。

有关创建索引的语法信息,您可以浏览此手册页面:

http://www.w3schools.com/sql/sql_create_index.asp

【讨论】:

以上是关于优化超过 200,000 条记录的查询的主要内容,如果未能解决你的问题,请参考以下文章

建议“优化 SQL 查询的响应时间”

优化繁重的 BigQuery DELETE 查询

Laravel - 使用大数据优化更新/插入查询的最佳方法是啥?

MySQL的limit 优化

这个查询有啥问题?从超过 220,000 条记录的 mysql 表中加载数据需要 0.5 到 0.6 秒

Delphi查询优化