Mysql 当列是复合键的一部分时未使用索引
我有两个巨大的表,我从中选择了大量的数据 表存储采购订单详细信息和产品信息Mysql 当列是复合键的一部分时未使用索引,mysql,indexing,query-performance,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, `OR
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条记录)
解释上述查询的输出
+----+-------------+-------+--------+-------------------------------------+----------------------------+---------+--------------------------------------------------------+-------+-------------+
| 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)
两个数据库具有相同的字符集
联接中使用的列具有相同的排序
两个表具有相同的字符集
我创建了一个新表,其中主键是连接列purcase\u ORDER\u NUMBER\u PF和PRODUCT\u CODE\u PF的,然后我在PRODUCT\u CODE\u PF上添加了一个新索引
在这种情况下是否将使用索引和/或这是在联接中使用索引的最佳方式
谢谢这些可能会有帮助:
MPO: INDEX(BATCH_ID, PURCHASE_ORDER_NUMBER_PK) -- in this order
EXP: INDEX(EXPENSE_CODE_ID_PK) -- unless it is the PRIMARY KEY
但是,在不知道“某些专栏”中有什么内容的情况下,我无法预测它们会有多大帮助。对于MPO和EXP,让显示创建表会有所帮助
你有多少公羊?innodb\u buffer\u pool\u size的值是多少?我这样问是因为你可能会大发雷霆。你有一本电话簿,上面有你镇上所有人的电话。你想给他们打电话。引用包含人名和姓氏的索引有什么意义吗?或者,当你试图调用所有人时,一页一页地查找索引是否更明智?这就是为什么你的索引没有被使用——它只是毫无意义,它什么也不做。您正在选择所有记录。@N.B.-请检查编辑,我又添加了一个具有相同问题的示例。MySQL optimizer是基于成本的,计算所需时间较少。。随机磁盘I/O非常昂贵,尤其是在使用普通HDD时。。不知道最新的MySQL优化器(8.0)是否能更好地使用SSD进行优化,或者是否能检测到SSD磁盘..因此MySQL在索引查找(14283随机磁盘I/O)上选择了全表扫描(1个随机磁盘I/O和顺序读取)。。。。。。想象一下,如果磁盘的寻道时间是10毫秒。全表扫描将在10毫秒内找到此信息。。索引查找将花费14283*10=142830ms,即2.3805分钟EXPLAIN query FORMAT=JSON
将更好地了解执行某些不同查询计划所需的成本(如果您的MySQL版本支持的话)是否存在问题?我的意思是,如果这是缓慢的,这不是因为没有使用索引。索引有助于查找和排序数据。如果您选择并发送1M行,那么传输和接收的数据量将使此操作变慢。
MPO: INDEX(BATCH_ID, PURCHASE_ORDER_NUMBER_PK) -- in this order
EXP: INDEX(EXPENSE_CODE_ID_PK) -- unless it is the PRIMARY KEY