2017-01-26 15 views
0

У меня есть 2 сервера mysql (master и slave). Я включил сжатие InnoDB на Slave, после чего mysql иногда выбирает неверный индекс для запроса.Mysql неверный индекс после сжатия InnoDB

Объясните на Master:

 

+----+-------------+-------+--------+---------------+---------+---------+-----------------------------+-----------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref       | rows  | Extra  | 
+----+-------------+-------+--------+---------------+---------+---------+-----------------------------+-----------+-------------+ 
| 1 | SIMPLE  | p  | range | PRIMARY  | PRIMARY | 8  | NULL      | 112017572 | Using where | 
| 1 | SIMPLE  | l  | eq_ref | PRIMARY  | PRIMARY | 8  |   p.loan_ID  |   1 | NULL  | 
| 1 | SIMPLE  | af | eq_ref | PRIMARY  | PRIMARY | 8  |   p.fromAccount_ID |   1 | Using where | 
| 1 | SIMPLE  | at | eq_ref | PRIMARY  | PRIMARY | 8  |   p.toAccount_ID |   1 | Using where | 
+----+-------------+-------+--------+---------------+---------+---------+-----------------------------+-----------+-------------+ 

Объясните на Ведомый:

 

+----+-------------+-------+--------+-------------------------------------------------------------------------------+--------------------+---------+-----------------------------+--------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys                 | key    | key_len | ref       | rows | Extra          | 
+----+-------------+-------+--------+-------------------------------------------------------------------------------+--------------------+---------+-----------------------------+--------+----------------------------------------------+ 
| 1 | SIMPLE  | l  | index | PRIMARY                  | FK243910AAD869E6 | 9  | NULL      | 804876 | Using index; Using temporary; Using filesort | 
| 1 | SIMPLE  | p  | ref | PRIMARY,FK4BE7532292C5D482,FK4BE75322AE503A13,FK4BE75322382D11BC,POSTING_DATE | FK4BE75322382D11BC | 9  |   l.ID    | 101 | Using index condition; Using where   | 
| 1 | SIMPLE  | af | eq_ref | PRIMARY                  | PRIMARY   | 8  |   p.fromAccount_ID |  1 | Using where         | 
| 1 | SIMPLE  | at | eq_ref | PRIMARY                  | PRIMARY   | 8  |   p.toAccount_ID |  1 | Using where         | 
+----+-------------+-------+--------+-------------------------------------------------------------------------------+--------------------+---------+-----------------------------+--------+----------------------------------------------+ 
SELECT 
     p.ID AS 'payment_id', 
     p.loan_ID AS 'loan_id', 
     l.client_ID AS 'client_ID', 
     p.amount AS 'amount', 
     p.postingDate AS 'payment_date', 
      CASE 
       WHEN af.acc_type = 'POLCH' THEN 'wallet'  
       WHEN af.acc_type = 'PLTCH' THEN 'wallet'   
       WHEN af.acc_type = 'CNTT' THEN 'bank'   
       WHEN af.acc_type = 'CNT2' THEN 'bank'   
       WHEN af.acc_type = 'KONCH' THEN 'bank'   
       WHEN af.acc_type = 'KRDTM' THEN 'cash'   
       WHEN af.acc_type = 'LDRCH' THEN 'bank'   
       ELSE concat('UNKNOWN_',af.acc_type) 
       END AS 'payment_system_type', 
     af.description AS 'payment_system' 
     FROM Posting AS p 
     INNER JOIN Account AS af ON p.fromAccount_ID = af.ID 
     INNER JOIN Account AS at ON p.toAccount_ID = at.ID 
     INNER JOIN Loan AS l ON p.loan_id = l.ID 
     WHERE ( 
      af.acc_type = 'KONCH' 
      OR af.acc_type = 'PLTCH' 
      OR af.acc_type = 'POLCH' 
      OR af.acc_type = 'KRDTM' 
      OR af.acc_type = 'LDRCH' 
      OR af.acc_type = 'CNT2' 
      OR af.acc_type = 'CNTT') 
      AND at.acc_type = 'ABON' 
      AND p.postingDate < DATE(now()) 
      AND p.ID > 0 
ORDER BY p.ID LIMIT 10000; 

Loan - л

Проводка - P

Master:

| Loan | CREATE TABLE `Loan` (
    `ID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `amount` decimal(19,4) DEFAULT NULL, 
    `amountToReturn` decimal(19,4) DEFAULT NULL, 
    `isGivenOut` bit(1) DEFAULT b'0', 
    `isPaid` bit(1) DEFAULT NULL, 
    `issueDate` datetime DEFAULT NULL, 
    `loanPeriod` int(11) DEFAULT NULL, 
    `productType` varchar(255) DEFAULT NULL, 
    `realPayDate` datetime DEFAULT NULL, 
    `client_ID` bigint(20) DEFAULT NULL, 
    `product_ID` bigint(20) DEFAULT NULL, 
    `givenOutDate` datetime DEFAULT NULL, 
    `isPaidByBank` bit(1) DEFAULT NULL, 
    `accountNumberNBKI` varchar(255) DEFAULT NULL, 
    `needManualProcessing` bit(1) DEFAULT NULL, 
    `isReverted` bit(1) DEFAULT b'0', 
    `showInNBCHReport` bit(1) DEFAULT b'1', 
    `stake` decimal(19,5) DEFAULT NULL, 
    `ignoreProlongation` bit(1) DEFAULT b'0', 
    `stakeAfter21` decimal(19,5) DEFAULT NULL, 
    `discount_id` bigint(20) DEFAULT NULL, 
    `showInEquifaxReport` bit(1) DEFAULT b'1', 
    `ignoreNbch` bit(1) DEFAULT b'0', 
    PRIMARY KEY (`ID`), 
    KEY `FK2439106EC0BA18` (`product_ID`), 
    KEY `ISPAID_INDEX` (`isPaid`) USING BTREE, 
    KEY `ISP_ISGOUT_INDEX` (`isPaid`,`isGivenOut`), 
    KEY `ISSUEDATE_INDEX` (`issueDate`), 
    KEY `FK243910735827C6` (`discount_id`), 
    KEY `idx_Loan_realPayDate` (`realPayDate`), 
    KEY `idx_Loan_givenOutDate` (`givenOutDate`), 
    KEY `FK243910AAD869E6` (`client_ID`), 
    CONSTRAINT `_FK243910735827C6` FOREIGN KEY (`discount_id`) REFERENCES `Discount` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2000623399 DEFAULT CHARSET=utf8 

Posting | CREATE TABLE `Posting` (
    `ID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `amount` decimal(19,4) DEFAULT NULL, 
    `postingDate` datetime DEFAULT NULL, 
    `fromAccount_ID` bigint(20) DEFAULT NULL, 
    `loan_ID` bigint(20) DEFAULT NULL, 
    `toAccount_ID` bigint(20) DEFAULT NULL, 
    `sourceType` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `FK4BE7532292C5D482` (`fromAccount_ID`), 
    KEY `FK4BE75322AE503A13` (`toAccount_ID`), 
    KEY `FK4BE75322382D11BC` (`loan_ID`), 
    KEY `POSTING_DATE` (`postingDate`) USING BTREE 
) ENGINE=InnoDB AUTO_INCREMENT=230996702 DEFAULT CHARSET=utf8 

Подчиненный:

| Loan | CREATE TABLE `Loan` (
    `ID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `amount` decimal(19,4) DEFAULT NULL, 
    `amountToReturn` decimal(19,4) DEFAULT NULL, 
    `isGivenOut` bit(1) DEFAULT b'0', 
    `isPaid` bit(1) DEFAULT NULL, 
    `issueDate` datetime DEFAULT NULL, 
    `loanPeriod` int(11) DEFAULT NULL, 
    `productType` varchar(255) DEFAULT NULL, 
    `realPayDate` datetime DEFAULT NULL, 
    `client_ID` bigint(20) DEFAULT NULL, 
    `product_ID` bigint(20) DEFAULT NULL, 
    `givenOutDate` datetime DEFAULT NULL, 
    `isPaidByBank` bit(1) DEFAULT NULL, 
    `accountNumberNBKI` varchar(255) DEFAULT NULL, 
    `needManualProcessing` bit(1) DEFAULT NULL, 
    `isReverted` bit(1) DEFAULT b'0', 
    `showInNBCHReport` bit(1) DEFAULT b'1', 
    `stake` decimal(19,5) DEFAULT NULL, 
    `ignoreProlongation` bit(1) DEFAULT b'0', 
    `stakeAfter21` decimal(19,5) DEFAULT NULL, 
    `discount_id` bigint(20) DEFAULT NULL, 
    `showInEquifaxReport` bit(1) DEFAULT b'1', 
    `ignoreNbch` bit(1) DEFAULT b'0', 
    PRIMARY KEY (`ID`), 
    KEY `FK2439106EC0BA18` (`product_ID`), 
    KEY `ISPAID_INDEX` (`isPaid`) USING BTREE, 
    KEY `ISP_ISGOUT_INDEX` (`isPaid`,`isGivenOut`), 
    KEY `ISSUEDATE_INDEX` (`issueDate`), 
    KEY `FK243910735827C6` (`discount_id`), 
    KEY `idx_Loan_realPayDate` (`realPayDate`), 
    KEY `idx_Loan_givenOutDate` (`givenOutDate`), 
    KEY `FK243910AAD869E6` (`client_ID`), 
    CONSTRAINT `_FK243910735827C6` FOREIGN KEY (`discount_id`) REFERENCES `Discount` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2000623399 DEFAULT CHARSET=utf8 
ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 

Posting | CREATE TABLE `Posting` (
    `ID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `amount` decimal(19,4) DEFAULT NULL, 
    `postingDate` datetime DEFAULT NULL, 
    `fromAccount_ID` bigint(20) DEFAULT NULL, 
    `loan_ID` bigint(20) DEFAULT NULL, 
    `toAccount_ID` bigint(20) DEFAULT NULL, 
    `sourceType` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `FK4BE7532292C5D482` (`fromAccount_ID`), 
    KEY `FK4BE75322AE503A13` (`toAccount_ID`), 
    KEY `FK4BE75322382D11BC` (`loan_ID`), 
    KEY `POSTING_DATE` (`postingDate`) USING BTREE 
) ENGINE=InnoDB AUTO_INCREMENT=230996702 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 

Если удалить таблицу ссуде из Query

 
+----+-------------+-------+--------+------------------------------------------------------------+---------+---------+-----------------------------+-----------+-------------+ 
| id | select_type | table | type | possible_keys            | key  | key_len | ref       | rows  | Extra  | 
+----+-------------+-------+--------+------------------------------------------------------------+---------+---------+-----------------------------+-----------+-------------+ 
| 1 | SIMPLE  | p  | range | PRIMARY,FK4BE7532292C5D482,FK4BE75322AE503A13,POSTING_DATE | PRIMARY | 8  | NULL      | 107736559 | Using where | 
| 1 | SIMPLE  | af | eq_ref | PRIMARY             | PRIMARY | 8  | smsfinance.p.fromAccount_ID |   1 | Using where | 
| 1 | SIMPLE  | at | eq_ref | PRIMARY             | PRIMARY | 8  | smsfinance.p.toAccount_ID |   1 | Using where | 
+----+-------------+-------+--------+------------------------------------------------------------+---------+---------+-----------------------------+-----------+-------------+ 

Если добавить создать индекс согл на счет (acc_type);

План:

 
+----+-------------+-------+--------+-------------------------------------------------------------------------------+--------------------+---------+---------------------------+------+--------------------------------------------------------+ 
| id | select_type | table | type | possible_keys                 | key    | key_len | ref      | rows | Extra             | 
+----+-------------+-------+--------+-------------------------------------------------------------------------------+--------------------+---------+---------------------------+------+--------------------------------------------------------+ 
| 1 | SIMPLE  | af | range | PRIMARY,acc                 | acc    | 21  | NULL      | 4192 | Using index condition; Using temporary; Using filesort | 
| 1 | SIMPLE  | p  | ref | PRIMARY,FK4BE7532292C5D482,FK4BE75322AE503A13,FK4BE75322382D11BC,POSTING_DATE | FK4BE7532292C5D482 | 9  | smsfinance.af.ID   | 54 | Using index condition; Using where      | 
| 1 | SIMPLE  | l  | eq_ref | PRIMARY                  | PRIMARY   | 8  | smsfinance.p.loan_ID  | 1 | NULL             | 
| 1 | SIMPLE  | at | eq_ref | PRIMARY,acc                 | PRIMARY   | 8  | smsfinance.p.toAccount_ID | 1 | Using where           | 
+----+-------------+-------+--------+-------------------------------------------------------------------------------+--------------------+---------+---------------------------+------+--------------------------------------------------------+ 

запроса выполнить долгое время.

+0

Существует много причин, почему это может произойти. Предоставьте 'SHOW CREATE TABLE' для' l' и 'p', плюс запрос, о котором идет речь. Я сомневаюсь, что сжатие имеет значение. Какая версия (-ы) - это mysqls? –

+0

Редактировать главный пост. – unknown

ответ

0

Я подозреваю, что сжатие приводит к разной статистике, что может привести к разным планам выполнения.

В этом вопросе я не вижу смысла использовать таблицу Loan. Удаление из запроса может привести к тому, что планы объяснения будут одинаковыми.

У вас есть 200M строк в каждой таблице? Еще одним ускорением будет сокращение таблиц.

  • Изменение BIGINT (8 байт каждый) до INT UNSIGNED (4 байта, диапазон 0..4 млрд), где это возможно.
  • Нормализовать столбцы _type, заменяя SMALLINT UNSIGNED (2 байта, диапазон 0..64K) или другого подходящего целочисленного типа. Или превратите столбец в ENUM, если есть конечное небольшое число «типов».

Account имеет INDEX(acc_type)? (Или, по крайней мере, начиная с acc_type.)

Удалить INNER JOIN Loan AS l ON p.loan_id = l.ID и заменить l.client_ID AS 'client_ID', с

(SELECT client_ID FROM Loans WHERE ID = p.loan_id) AS 'client_ID', 

Я думаю, что это заставит другой план запроса, возможно, хороший.

+0

Извините, я ошибся в запросе. Теперь в запросе присутствуют таблицы Loan. – unknown

+0

Нет, у учетной записи есть индекс с acc_type и client_ID 'UNIQUE KEY 'idx_unique_client_acc_type' (' client_ID', 'acc_type')' – unknown

+0

Мне нужен индекс _starting_ с acc_type. –