MariaDB 内部连接很慢
MariaDB Inner join is slow
这是我的SQL(有解释):
EXPLAIN
UPDATE
VF_KRED kred
INNER JOIN GBI gbi ON
kred.vendor = gbi.vendor
INNER JOIN MASTER_DATA master_data ON
master_data.vendor_code = gbi.vendor
SET
kred.GBI_VAL_REP =
(CASE
WHEN kred.country = 'JP' THEN
CASE
WHEN gbi.WITHHOLD_TAX_CODE = 0 THEN 2
WHEN gbi.WITHHOLD_TAX_CODE = 'IN' THEN 1
END
ELSE
CASE
WHEN gbi.WITHHOLD_TAX_CODE = master_data.REDUCED_RATE THEN
CASE
WHEN gbi.WITHHOLD_TAX_CODE = 0 THEN 3
WHEN gbi.WITHHOLD_TAX_CODE BETWEEN 1 AND 19 THEN 4
END
ELSE 5
END
END);
给出以下结果:
现在,UPDATE
SQL 需要大约 6 分钟以上。
以下是 tables 上的索引:
- VF_KRED table:
- GBI table:
- MASTER_DATA table:
VENDOR
列都是varchar(25)
类型。
-- 编辑:(下面描述整个 table 结构):
SHOW CREATE TABLE GBI;
CREATE TABLE `GBI` (
`VENDOR` varchar(25) CHARACTER SET utf8 NOT NULL,
`COMPANY_CODE` varchar(5) CHARACTER SET latin1 NOT NULL DEFAULT '',
`VENDOR_NAME` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '',
`WITHHOLD_TAX_TYPE` varchar(2) CHARACTER SET latin1 NOT NULL DEFAULT '',
`WITHHOLD_TAX_CODE` varchar(2) CHARACTER SET latin1 NOT NULL DEFAULT '',
`DOCUMENT_CURRENCY` varchar(4) CHARACTER SET latin1 NOT NULL DEFAULT '',
`CREATE_DT` datetime NOT NULL,
PRIMARY KEY (`VENDOR`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE VF_KRED;
CREATE TABLE `VF_KRED` (
`VENDOR` varchar(25) CHARACTER SET latin1 NOT NULL,
`COUNTRY_CODE` varchar(5) CHARACTER SET latin1 DEFAULT NULL,
`COUNTRY` varchar(3) CHARACTER SET latin1 DEFAULT NULL,
`SEARCH_TERM` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
`CREATE_DT` datetime DEFAULT NULL,
`GBI_VAL_REP` int(11) NOT NULL DEFAULT 5,
PRIMARY KEY (`VENDOR`),
KEY `vf_kred` (`GBI_VAL_REP`),
KEY `VF_KRED_COUNTRY_IDX` (`COUNTRY`) USING BTREE,
CONSTRAINT `vf_kred_ibfk_1` FOREIGN KEY (`GBI_VAL_REP`) REFERENCES `VENDOR_RATE_CATEGORY` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE MASTER_DATA;
CREATE TABLE `MASTER_DATA` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`VENDOR_CODE` varchar(25) CHARACTER SET latin1 DEFAULT NULL,
`VENDOR_NAME` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`COUNTRY` varchar(2) CHARACTER SET latin1 DEFAULT NULL,
`APPLN_RECEIVED_FROM_US` datetime DEFAULT NULL,
`ITUNES_CONTRACT_NUM` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`CONTRACT_EFFECTIVE_DT` datetime DEFAULT NULL,
`CONTRACT_EXPIRATION_DT` datetime DEFAULT NULL,
`AUTO_RENEWAL` varchar(10) CHARACTER SET latin1 DEFAULT NULL,
`REDUCED_RATE` int(11) DEFAULT NULL,
`FORM_17` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`RESIDENCY_CERT_ISSUE_DT` datetime DEFAULT NULL,
`TAX_AUTHORITY_SUBMISSION_DT` datetime DEFAULT NULL,
`TAX_AUTHORITY_ACCEPTANCE_DT` datetime DEFAULT NULL,
`STATUS` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`FORM_17_EXPIRATION` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`COMMENTS` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`REMARKS` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`CATEGORY` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `MASTER_DATA_VENDOR_CODE_IDX` (`VENDOR_CODE`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2369 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
有什么线索吗?
不要在需要比较的列上混用 CHARACTER SETs
(或数据类型或排序规则),如 JOIN
。请注意 vendor
是 latin1
与 utf8
的区别。这会减慢 JOIN
。 (此外,检查 vendor_code
由于另一个连接。)
EXPLAIN
中的线索:"func"。这意味着 vendor
以某种方式被修改以执行 JOIN
。 CREATE TABLE
表明字符集不同。
如果您只有 1GB 的 RAM,128MB for innodb_buffer_pool_size
是合适的,甚至是可取的。对于 8GB,6G
会是一个更好的设置。通过增加该值,您可能会减少 I/O 此查询和其他查询所必需的 I/O。同样,这会影响 JOIN
.
的速度
这是我的SQL(有解释):
EXPLAIN
UPDATE
VF_KRED kred
INNER JOIN GBI gbi ON
kred.vendor = gbi.vendor
INNER JOIN MASTER_DATA master_data ON
master_data.vendor_code = gbi.vendor
SET
kred.GBI_VAL_REP =
(CASE
WHEN kred.country = 'JP' THEN
CASE
WHEN gbi.WITHHOLD_TAX_CODE = 0 THEN 2
WHEN gbi.WITHHOLD_TAX_CODE = 'IN' THEN 1
END
ELSE
CASE
WHEN gbi.WITHHOLD_TAX_CODE = master_data.REDUCED_RATE THEN
CASE
WHEN gbi.WITHHOLD_TAX_CODE = 0 THEN 3
WHEN gbi.WITHHOLD_TAX_CODE BETWEEN 1 AND 19 THEN 4
END
ELSE 5
END
END);
给出以下结果:
现在,UPDATE
SQL 需要大约 6 分钟以上。
以下是 tables 上的索引:
- VF_KRED table:
- GBI table:
- MASTER_DATA table:
VENDOR
列都是varchar(25)
类型。
-- 编辑:(下面描述整个 table 结构):
SHOW CREATE TABLE GBI;
CREATE TABLE `GBI` (
`VENDOR` varchar(25) CHARACTER SET utf8 NOT NULL,
`COMPANY_CODE` varchar(5) CHARACTER SET latin1 NOT NULL DEFAULT '',
`VENDOR_NAME` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '',
`WITHHOLD_TAX_TYPE` varchar(2) CHARACTER SET latin1 NOT NULL DEFAULT '',
`WITHHOLD_TAX_CODE` varchar(2) CHARACTER SET latin1 NOT NULL DEFAULT '',
`DOCUMENT_CURRENCY` varchar(4) CHARACTER SET latin1 NOT NULL DEFAULT '',
`CREATE_DT` datetime NOT NULL,
PRIMARY KEY (`VENDOR`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE VF_KRED;
CREATE TABLE `VF_KRED` (
`VENDOR` varchar(25) CHARACTER SET latin1 NOT NULL,
`COUNTRY_CODE` varchar(5) CHARACTER SET latin1 DEFAULT NULL,
`COUNTRY` varchar(3) CHARACTER SET latin1 DEFAULT NULL,
`SEARCH_TERM` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
`CREATE_DT` datetime DEFAULT NULL,
`GBI_VAL_REP` int(11) NOT NULL DEFAULT 5,
PRIMARY KEY (`VENDOR`),
KEY `vf_kred` (`GBI_VAL_REP`),
KEY `VF_KRED_COUNTRY_IDX` (`COUNTRY`) USING BTREE,
CONSTRAINT `vf_kred_ibfk_1` FOREIGN KEY (`GBI_VAL_REP`) REFERENCES `VENDOR_RATE_CATEGORY` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE MASTER_DATA;
CREATE TABLE `MASTER_DATA` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`VENDOR_CODE` varchar(25) CHARACTER SET latin1 DEFAULT NULL,
`VENDOR_NAME` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`COUNTRY` varchar(2) CHARACTER SET latin1 DEFAULT NULL,
`APPLN_RECEIVED_FROM_US` datetime DEFAULT NULL,
`ITUNES_CONTRACT_NUM` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`CONTRACT_EFFECTIVE_DT` datetime DEFAULT NULL,
`CONTRACT_EXPIRATION_DT` datetime DEFAULT NULL,
`AUTO_RENEWAL` varchar(10) CHARACTER SET latin1 DEFAULT NULL,
`REDUCED_RATE` int(11) DEFAULT NULL,
`FORM_17` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`RESIDENCY_CERT_ISSUE_DT` datetime DEFAULT NULL,
`TAX_AUTHORITY_SUBMISSION_DT` datetime DEFAULT NULL,
`TAX_AUTHORITY_ACCEPTANCE_DT` datetime DEFAULT NULL,
`STATUS` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`FORM_17_EXPIRATION` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`COMMENTS` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`REMARKS` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`CATEGORY` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `MASTER_DATA_VENDOR_CODE_IDX` (`VENDOR_CODE`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2369 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
有什么线索吗?
不要在需要比较的列上混用 CHARACTER SETs
(或数据类型或排序规则),如 JOIN
。请注意 vendor
是 latin1
与 utf8
的区别。这会减慢 JOIN
。 (此外,检查 vendor_code
由于另一个连接。)
EXPLAIN
中的线索:"func"。这意味着 vendor
以某种方式被修改以执行 JOIN
。 CREATE TABLE
表明字符集不同。
128MB for innodb_buffer_pool_size
是合适的,甚至是可取的。对于 8GB,6G
会是一个更好的设置。通过增加该值,您可能会减少 I/O 此查询和其他查询所必需的 I/O。同样,这会影响 JOIN
.