【问题标题】:Why is mysql not using index when available为什么mysql在可用时不使用索引
【发布时间】:2016-09-27 10:51:34
【问题描述】:

我有一个非常慢的查询,我不知道为什么,每个连接字段都有索引。

这是我的查询:

    SELECT 
    CASE
        WHEN
            arrears_action.executed IS NULL
                OR arrears_action.executed != '0000-00-00 00:00:00'
        THEN
            'No action'
        ELSE DATE_FORMAT(arrears_action.planned, '%d %M %Y')
    END,
    CASE
        WHEN
            arrears_action.executed IS NULL
                OR arrears_action.executed != '0000-00-00 00:00:00'
        THEN
            NULL
        ELSE IF(DATEDIFF(NOW(), arrears_action.planned) >= 0,
            DATEDIFF(NOW(), arrears_action.planned),
            NULL)
    END,
    customer.id AS customer_id,
    customer.customer_number AS cif_number,
    arrears_application.id AS arrears_application_id,
    person.id AS person_id,
    person.fullname,
    account.account_number,
    CONCAT(branch.branch_id,
            product.code,
            SUBSTRING(contract.loan_number, - 9, 9)) AS loan_account,
    payment.principal_amount_outstanding,
    arrears.amount_in_arrears,
    arrears.days_in_arrears,
    balance.account_balance_available,
    product.code AS product_code,
    division.name AS division_name,
    coll_customer_status.name AS customer_status,
    loan_status.name AS loan_status
FROM
    cregora_cregora.base_cregora_loancontract_inarrears_data AS arrears 
        INNER JOIN
    cregora_cregora.base_cregora_loancontract_data AS contract ON contract.id = arrears.loancontract_id 
        INNER JOIN
    cregora_cregora.base_cregora_loancontract_payment_data AS payment ON payment.loancontract_id = contract.id
        INNER JOIN
    cregora_cregora.base_cregora_nmb_product_class_data AS product ON product.id = contract.product_class
        INNER JOIN
    cregora_cregora.base_cregora_account_data AS account ON account.id = contract.account_id
        INNER JOIN
    cregora_cregora.base_cregora_customer_data AS customer ON customer.id = account.customer_id
        INNER JOIN
    cregora_cregora.base_cregora_person_data AS person ON person.id = customer.type_of_customer_id
        INNER JOIN
    cregora_base.system_organization_division AS division ON division.id = contract.loan_branch
        INNER JOIN
    cregora_cregora.base_cregora_nmb_branch_data AS branch ON branch.id = division.entity_instance_id
        INNER JOIN
    cregora_cregora.base_cregora_account_balanceinfo_daily_data AS balance ON balance.account_id = account.id
        LEFT JOIN
    cregora_cregora.base_cregora_arrears_applications_data AS arrears_application ON arrears_application.loan_contract_number = contract.loan_number
        LEFT JOIN
    cregora_cregora.base_cregora_arrears_action_data AS arrears_action ON arrears_action.arrears_application_id = arrears_application.id
        LEFT JOIN
    cregora_cregora.base_cregora_collection_applications_data AS coll_application ON coll_application.arrears_application_id = arrears_application.id
        LEFT JOIN
    cregora_cregora.base_cregora_collection_customer_statuses_data AS coll_customer_status ON coll_customer_status.id = coll_application.collection_customer_status_id
        LEFT JOIN
    cregora_cregora.base_cregora_arrears_loan_contract_statuses_data AS loan_status ON loan_status.id = arrears_application.loan_contract_status_id
        LEFT JOIN
    cregora_cregora.base_cregora_arrears_application_statuses_data AS arrears_status ON arrears_status.id = arrears_application.arrears_application_status_id
WHERE
    contract.loan_branch IN (46)
        AND (coll_customer_status.id IN ('1' , '2',
        '3',
        '5',
        '6',
        '7',
        '8',
        '9',
        '10',
        '11',
        '12',
        '13',
        '15',
        '16',
        '17',
        '18',
        '19',
        '20',
        '21',
        '22',
        '23')
        OR coll_customer_status.id IS NULL)
        AND (loan_status.id IS NULL
        OR loan_status.id IN ('1' , '2', '3', '4', '5'))
        AND arrears.amount_in_arrears > '1'
GROUP BY arrears_application.id
ORDER BY arrears.days_in_arrears DESC , person.fullname

这是 EXPLAIN 的输出: 为什么mysql不使用合约表的任何索引(第三行解释,type-> ALL,可能的键->PRIMARY,account_id,loan_branch,product_class key->empty?

提前谢谢

【问题讨论】:

  • 您能否让您的解释更具可读性。它可能没有使用索引,原因很简单,因为它不需要!为什么你担心它是查询慢?如果是这样,请给出时间并指出每个表中的行数
  • 使用图片而不是文本输出,如您所见,合同表未使用任何索引。它正在执行全表扫描。我还不确定记录的数量,因为我仍在导入实际的测试数据,但有很多。在生产中,此查询将运行 5 分钟左右。附加说明:当删除 group by 和 order by 子句时,查询下降到一秒以下
  • 在大型导入操作已在运行时进行任何类型的分析毫无意义
  • 是的,我知道,但是其他团队成员也进行了分析,所以我们知道查询运行了很长时间,并且它正在导入到我的本地数据库,顺便说一句不是生产,所以不是
  • show variables like 'optimizer_search_depth'; 的输出是什么?

标签: mysql indexing database-performance


【解决方案1】:

问题在于,arrears_application_data 表已加入但也按其分组。这导致性能显着下降

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-29
    • 2016-06-24
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    相关资源
    最近更新 更多