如果列是组合键的一部分,则不使用索引

时间:2018-07-10 10:43:10

标签: mysql indexing query-performance

我有两个巨大的表,可以从中选择大量数据。

表存储采购订单明细和产品信息。

    PURCHASE_ORDER_DETAILS.
    CREATE TABLE `PURCHASE_ORDER_DETAILS` (
    `PURCHASE_ORDER_NUMBER_PF` INT(20) NOT NULL,
    `PRODUCT_CODE_PF` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
    `ORDER_QUANTITY` INT(8) DEFAULT NULL,
    `UNIT_PRICE` DECIMAL(12,2) DEFAULT NULL,
    `ORDER_FULLFILLMENT_DUE_DATE` DATETIME DEFAULT NULL,
    `DELIVERY_ADDRESS` VARCHAR(64) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
    `DELIVERY_CITY` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
     `DELIVERY_ZIP` BIGINT(10) DEFAULT NULL,
     `other columns`
      PRIMARY KEY (`PURCHASE_ORDER_NUMBER_PF`,`PRODUCT_CODE_PF`),
      KEY `RMAPWBTX_PUCH_ORDE_DLST_INDX` (`DELIVERY_STATE_ID_FK`),
      KEY `RMAPWBTX_PUCH_ORDE_DLTY_INDX` (`DELIVERY_TYPE_FK`),
      KEY `RMAPWBTX_PUCH_ORDE_TACO_INDX` (`TAX_CODE_FK`),
      KEY `RMAPWBMS_PUOR_DETL_PDCO_FK` (`PRODUCT_CODE_PF`),
      KEY `RMAPWBTX_PUOR_DETL_TACO_FK` (`TAX_CODE_FK`),
      KEY `CREATED_DATE_INDX` (`CREATED_DATE`),
      KEY `MODIFIED_DATE_INDX` (`MODIFIED_DATE`),
      CONSTRAINT `RMAPWBMS_PUOR_DETL_PDCO_FK` FOREIGN KEY (`PRODUCT_CODE_PF`) 
      REFERENCES `PRODUCT` (`PRODUCT_CODE_PK`) ON DELETE NO ACTION ON UPDATE NO ACTION,
      CONSTRAINT `RMAPWBMS_PUOR_DETL_PONU_FK` FOREIGN KEY 
      (`PURCHASE_ORDER_NUMBER_PF`) REFERENCES `PURCHASE_ORDER` 
      (`PURCHASE_ORDER_NUMBER_PK`),
     CONSTRAINT `RMAPWBTX_PO_DETL_DSID_FK` FOREIGN KEY 
     (`DELIVERY_STATE_ID_FK`) REFERENCES `STATE` (`STATE_ID_PK`),
     CONSTRAINT `RMAPWBTX_PUOR_DETL_TACO_FK` FOREIGN KEY (`TAX_CODE_FK`) 
     REFERENCES `TAX` (`TAX_CODE_PK`) ON DELETE NO ACTION ON UPDATE NO ACTION
     ) ENGINE=INNODB DEFAULT CHARSET=latin1;


PRODUCT

    CREATE TABLE `PRODUCT` (
    `PRODUCT_CODE_PK` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
    `PRODUCT_DESC` VARCHAR(256) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
    `FEE_BILL_CODE` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
    `other columns`
     PRIMARY KEY (`PRODUCT_CODE_PK`),
     KEY `CREATED_DATE_INDX` (`CREATED_DATE`),
     KEY `MODIFIED_DATE_INDX` (`MODIFIED_DATE`),
     KEY `PRODUCT_EXCO_FK` (`EXPENSE_CODE_ID_FK`),
     KEY `FK_PRODUCT_ENTITY_TYPE` (`ENTITY_TYPE_CODE_FK`),
     CONSTRAINT `FK_PRODUCT_ENTITY_TYPE` FOREIGN KEY (`ENTITY_TYPE_CODE_FK`) REFERENCES `ENTITY_TYPE` (`ENTITY_TYPE_CODE_PK`)
     ) ENGINE=INNODB DEFAULT CHARSET=latin1

     Below query is taking ~10min to get ~1M records.

     EXPLAIN SELECT * FROM
     PURCHASE_ORDER_DETAILS POD
     JOIN PRODUCT PRD ON POD.PRODUCT_CODE_PF=PRD.PRODUCT_CODE_PK;
+----+-------------+-------+------+----------------------------+-----------------

    -----------+---------+-----------------------------------------------+-------+-------+
    | id | select_type | table | type | possible_keys              | key                        | key_len | ref                                           | rows  | Extra |
    +----+-------------+-------+------+----------------------------+----------------------------+---------+-----------------------------------------------+-------+-------+
    |  1 | SIMPLE      | PRD   | ALL  | PRIMARY                    | NULL                       | NULL    | NULL                                          | 14283 | NULL  |
    |  1 | SIMPLE      | POD   | ref  | RMAPWBMS_PUOR_DETL_PDCO_FK | RMAPWBMS_PUOR_DETL_PDCO_FK | 34      | REALREMIT_PROD_ALTISOURCE.PRD.PRODUCT_CODE_PK |    40 | NULL  |
    +----+-------------+-------+------+----------------------------+----------------------------+---------+-----------------------------------------------+-------+---

编辑1: 上面的查询是一个示例,下面是我尝试获取1M记录(主表POD具有22M记录)的实际查询。

SELECT `some columns`
FROM `REALREMIT_PPIPFC_MIG`.MIGR_ORDER_DENORM MPO
INNER JOIN PURCHASE_ORDER_DETAILS POD 
ON MPO.PURCHASE_ORDER_NUMBER_PK=POD.PURCHASE_ORDER_NUMBER_PF
INNER JOIN PRODUCT PRD 
ON POD.PRODUCT_CODE_PF=PRD.PRODUCT_CODE_PK 
INNER JOIN EXPENSE_CODE EXP
ON PRD.EXPENSE_CODE_ID_FK=EXP.EXPENSE_CODE_ID_PK 
WHERE MPO.BATCH_ID=1;

解释上述查询的输出

+----+-------------+-------+--------+-------------------------------------+----------------------------+---------+--------------------------------------------------------+-------+-------------+
| id | select_type | table | type   | possible_keys                       | key                        | key_len | ref                                                    | rows  | Extra       |
+----+-------------+-------+--------+-------------------------------------+----------------------------+---------+--------------------------------------------------------+-------+-------------+
|  1 | SIMPLE      | PRD   | ALL    | PRIMARY,PRODUCT_EXCO_FK             | NULL                       | NULL    | NULL                                                   | 14283 | NULL        |
|  1 | SIMPLE      | EXP   | eq_ref | PRIMARY                             | PRIMARY                    | 4       | REALREMIT_PROD_ALTISOURCE.PRD.EXPENSE_CODE_ID_FK       |     1 | NULL        |
|  1 | SIMPLE      | POD   | ref    | PRIMARY,RMAPWBMS_PUOR_DETL_PDCO_FK  | RMAPWBMS_PUOR_DETL_PDCO_FK | 34      | REALREMIT_PROD_ALTISOURCE.PRD.PRODUCT_CODE_PK          |    40 | NULL        |
|  1 | SIMPLE      | MPO   | ref    | MIGR_PO_NBR_INDX,MIGR_BATCH_ID_INDX | MIGR_PO_NBR_INDX           | 4       | REALREMIT_PROD_ALTISOURCE.POD.PURCHASE_ORDER_NUMBER_PF |     1 | Using where |
+----+-------------+-------+--------+-------------------------------------+----------------------------+---------+--------------------------------------------------------+-------+-------------+
4 rows in set (0.20 sec)
  

两个数据库都具有相同的字符集   连接中使用的列具有相同的排序规则   两个表都有相同的字符集

我创建了一个新表,该表中的主键是连接列-PURHCASE_ORDER_NUMBER_PF和PRODUCT_CODE_PF,然后在PRODUCT_CODE_PF上添加了新索引 在这种情况下将使用索引,并且/或者这是在连接中使用索引的最佳方法。

谢谢

1 个答案:

答案 0 :(得分:0)

这些可能会帮助您

MPO:  INDEX(BATCH_ID, PURCHASE_ORDER_NUMBER_PK)   -- in this order
EXP:  INDEX(EXPENSE_CODE_ID_PK)   -- unless it is the PRIMARY KEY

但是,在不知道“某些列”中有什么的情况下,我无法预测它们会提供多少帮助。拥有SHOW CREATE TABLE用于MPO和EXP会有所帮助。

您有多少RAM? innodb_buffer_pool_size的值是什么?我问,因为你可能会rash打。