2016-03-30 5 views
0

Я включил медленный монитор запросов в MySQL config.улучшить производительность запросов MySQL из медленного журнала запросов

Ниже запрос и время:

Время: 160330 20:54:11 Пользователь @ Хост: пользователь [пользователь] @ [xx.xx.xxx.xxx] Query_time: 8,794170 Lock_time: 0.000141 Rows_sent: 3942 Rows_examined: 4742825 SET timestamp = 1459371251;

SELECT (SELECT (CASE WHEN ce_type = 'IN' then SUM(payment_amount) 
           END) as debit 
         FROM customer_payment_options cpo 
         WHERE wallet_id=cw.id 
         AND (cpo.real_account_type='HQ') 
         AND cpo.source_country_id='40' 
         GROUP BY cpo.wallet_id) 
        as debit, 
        (SELECT SUM(payment_amount) 
           as credit 
         FROM customer_payment_options cpo 
         WHERE wallet_id=cw.id 
         AND (cpo.real_account_type='HQ') 
         AND cpo.tran_id IS NOT NULL 
         AND cpo.source_country_id='40' 
         GROUP BY cpo.wallet_id) 
        as credit 

        FROM customer_wallet cw 
        WHERE cw.company_id='1' 
        AND cw.currency='40' 
        AND cw.is_approved = '1' 
        AND DATE(cw.date_added) < '2016-03-30'; 

Индексы customer_payment_options:

company_id 
tran_id 
ce_id 
wallet_id 

Что я должен сделать, чтобы улучшить его производительность?

EXPLAIN:

http://i.stack.imgur.com/iH8rt.png

SCHEMA

CREATE TABLE `customer_payment_options` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`company_id` int(11) NOT NULL, 
`local_branch_id` int(11) NOT NULL, 
`tran_id` bigint(11) DEFAULT NULL, 
`ce_id` int(11) DEFAULT NULL, 
`wallet_id` int(11) DEFAULT NULL, 
`reward_credit_id` int(11) DEFAULT NULL, 
`ce_invoice_id` varchar(32) DEFAULT NULL, 
`ce_type` enum('IN','OUT') DEFAULT NULL, 
`payment_type` enum('CASH','DEBIT','CREDIT','CHEQUE','DRAFT','BANK_DEPOSIT','EWIRE','WALLET','LOAN','REWARD_CREDIT') NOT NULL, 
`payment_amount` varchar(20) NOT NULL, 
`payment_type_number` varchar(100) DEFAULT NULL, 
`source_country_id` int(11) NOT NULL, 
`real_account_id` int(11) DEFAULT NULL, 
`real_account_type` enum('LOCAL','HQ') DEFAULT NULL, 
`date_added` datetime NOT NULL, 
`event_type` enum('MONEY_TRANSFER','CURRENCY_EXCHANGE','WALLET') DEFAULT NULL, 
PRIMARY KEY (`id`), 
KEY `company_id` (`company_id`), 
KEY `real_account_type` (`real_account_type`), 
KEY `tran_id` (`tran_id`), 
KEY `ce_id` (`ce_id`), 
KEY `wallet_id` (`wallet_id`), 
CONSTRAINT `customer_payment_options_ibfk_4` FOREIGN KEY (`wallet_id`) REFERENCES `customer_wallet` (`id`), 
CONSTRAINT `customer_payment_options_ibfk_1` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`), 
CONSTRAINT `customer_payment_options_ibfk_2` FOREIGN KEY (`tran_id`) REFERENCES `transaction` (`id`), 
CONSTRAINT `customer_payment_options_ibfk_3` FOREIGN KEY (`ce_id`) REFERENCES `currency_exchange` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=412 DEFAULT CHARSET=utf8 

CREATE TABLE `customer_wallet` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`wallet_unique_id` varchar(100) DEFAULT NULL, 
`company_id` int(11) NOT NULL, 
`branch_admin_id` int(11) DEFAULT NULL, 
`emp_id` int(11) DEFAULT NULL, 
`emp_type` enum('SUPER_ADMIN','ADMIN','AGENT_ADMIN','AGENT','OVER_AGENT_ADMIN','OVER_AGENT') DEFAULT NULL, 
`cus_id` bigint(11) NOT NULL, 
`tran_id` bigint(11) DEFAULT NULL, 
`beehive_id` int(11) DEFAULT NULL, 
`type` enum('DEPOSIT','WITHDRAW','TRANSACTION') NOT NULL, 
`sub_type` enum('MONEY_TRANSFER','BEEHIVE_DEPOSIT') DEFAULT NULL, 
`credit_in` varchar(20) DEFAULT NULL, 
`credit_out` varchar(20) DEFAULT NULL, 
`currency` varchar(20) NOT NULL, 
`date_added` datetime NOT NULL, 
`note` varchar(255) DEFAULT NULL, 
`location` enum('DIRECT') DEFAULT NULL, 
`is_approved` enum('0','1') NOT NULL DEFAULT '1', 
`idebit_issconf` varchar(50) DEFAULT NULL, 
`idebit_issname` varchar(50) DEFAULT NULL, 
`idebit_isstrack2` varchar(100) DEFAULT NULL, 
PRIMARY KEY (`id`), 
KEY `cus_id` (`cus_id`), 
KEY `company_id` (`company_id`), 
KEY `branch_admin_id` (`branch_admin_id`), 
KEY `emp_id` (`emp_id`), 
KEY `tran_id` (`tran_id`), 
KEY `beehive_id` (`beehive_id`), 
CONSTRAINT `customer_wallet_ibfk_1` FOREIGN KEY (`cus_id`) REFERENCES `customers` (`id`), 
CONSTRAINT `customer_wallet_ibfk_2` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`), 
CONSTRAINT `customer_wallet_ibfk_3` FOREIGN KEY (`tran_id`) REFERENCES `transaction` (`id`), 
CONSTRAINT `customer_wallet_ibfk_4` FOREIGN KEY (`emp_id`) REFERENCES `employees` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=152 DEFAULT CHARSET=utf8 
+2

Вопросы производительности должны включать в себя «EXPLAIN ANALYZE» и некоторую информацию о размере таблицы, индексе, текущем времени, времени ожидания и т. Д. «Slow» - относительный термин, и нам нужно реальное значение для сравнения. [** MySQL **] (http://dba.stackexchange.com/questions/15371/how-do-i-get-the-execution-plan-for-a-view) и индекс MySQL [* * СОВЕТЫ **] (http://mysql.rjweb.org/doc.php/index_cookbook_mysql) –

+0

Я обновил EXPLAIN –

+0

Почему вы не вставляете изображение в сообщение напрямую? –

ответ

3

Что вы делаете в качестве коррелированного запроса на каждом кошелек ID, чтобы получить соответствующий дебет и кредит. Кажется, вы получаете одну запись за идентификатор кошелька. Это очень занято. Присоединение к таблице платежей клиентов по вашим критериям, которые являются общими (включая соединение на идентификатор кошелька). Затем упростите CASE как SUM (case/when) в качестве соответствующего дебетования/кредита.

Я не знаю ваших базовых критериев столбцов таблицы, но я бы даже хеджировал (и сделал) include NOT CE_TYPE = 'IN', поскольку это является основанием дебетования, и вы не хотели бы ошибочно считать, что часть кредита тоже. Опять же, не знаю корреляции полей, trans_id, типов.

Теперь, как указано, наличие отдельных индексов в отдельных полях не поможет оптимизировать этот запрос. Я бы предложил следующие индексы.

индекс таблицы customer_wallet (company_id, is_approved, валюта, идентификатор, DATE_ADDED) customer_payment_options (wallet_id, ACCOUNT_TYPE, country_id)

SELECT 
     cw.wallet_id, 
     SUM(case when cpo.ce_type = 'IN' 
       then cpo.payment_amount 
       ELSE 0 end) as Debit, 
     SUM(case when NOT cpo.ce_type = 'IN' 
        AND cpo.tran_id IS NOT NULL 
       then cpo.payment_amount 
       ELSE 0 end) as Credit 
    FROM 
     customer_wallet cw 
     JOIN customer_payment_options cpo 
      ON cw.id = cpo.wallet_id 
      AND cpo.real_account_type = 'HQ' 
      AND cpo.source_country_id = '40' 
    WHERE 
      cw.company_id = '1' 
     AND cw.currency = '40' 
     AND cw.is_approved = '1' 
     AND cw.date_added < '2016-03-30' 
    GROUP BY 
     cw.id 

Один дополнительный комментарий. если ваши идентификационные столбцы, флаг валюты, идентификатор страны, одобрены, фактически являются числовыми значениями в структуре таблицы, удаляют кавычки и позволяют сравнивать непосредственно с числовым значением. Кроме того, для вашего date_added. У вас это было на основе DATE (date_added). Выполнение функции в столбце не может полностью использовать индекс. Поскольку date() отбрасывает любую временную часть столбца даты/времени и вы запрашиваете все добавленные меньше, чем 30 марта, то добавленная дата 29 марта 29:59:59 все еще меньше 30 марта в 12: 00:00, поэтому преобразование даты не требуется.

Как прокомментировал Иван (ниже), если вы хотите ВСЕ ИМЯ кошелька, независимо от наличия каких-либо платежей (дебет или кредит), затем переходите от объединения к ЛЕВЫМ СОЕДИНЕНИЕМ.

+0

Спасибо за ваши усилия. Я обновил схему таблицы в моем вопросе. –

+0

'customer_wallet cw JOIN customer_payment_options cpo' Я думаю, что это должно быть' left join'. –

+0

@IvanGritsenko, так отредактированный как окончательный комментарий к сообщению. Не уверены точно, чего они хотят, но подумают, что они хотят только тех, у кого есть активность, но могут быть неправильными. – DRapp

0

Вам нужно добавить индексы и индексы нескольких столбцов, чтобы сделать это быстро. Пожалуйста, имейте в виду, что если у вас есть большая таблица, дополнительные индексы замедлят вставки, поскольку обновление индексного файла займет больше времени.

Если индекс col1 и col2 существует с несколькими столбцами, соответствующие строки могут быть выбраны напрямую. Если существуют отдельные индексы с одним столбцом на col1 и col2, оптимизатор пытается использовать оптимизацию индекса (см. Раздел 8.2.1.4, «Оптимизация слияния индексов») или пытается найти наиболее ограничительный индекс, решив, какой индекс исключает больше строк и использует этот индекс для извлечения строк.

Если таблица имеет индекс с несколькими столбцами, любой левый префикс индекса может использоваться оптимизатором для поиска строк. Например, если у вас есть индекс с тремя столбцами (col1, col2, col3), вы указали возможности поиска в (col1), (col1, col2) и (col1, col2, col3).

Read more

Смежные вопросы