使用 MySQL 按空值分区
Partitions by null values with MySQL
我有一个 table:
CREATE TABLE `NewTable` (
`IBLOCK_ELEMENT_ID` int(11) NOT NULL ,
`PROPERTY_1836` int(11) NULL DEFAULT NULL ,
`DESCRIPTION_1836` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_1837` int(11) NULL DEFAULT 0 ,
`DESCRIPTION_1837` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_1838` decimal(18,4) NULL DEFAULT NULL ,
`DESCRIPTION_1838` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_3139` int(11) NULL DEFAULT 0 ,
`DESCRIPTION_3139` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_3173` decimal(18,4) NULL DEFAULT NULL ,
`DESCRIPTION_3173` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`IBLOCK_ELEMENT_ID`),
INDEX `ix_perf_b_iblock_element_pr_1` (`PROPERTY_1837`) USING BTREE ,
INDEX `ix_perf_b_iblock_element_pr_2` (`PROPERTY_1836`) USING BTREE ,
INDEX `ix_perf_b_iblock_element_pr_3` (`PROPERTY_3139`) USING BTREE
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=cp1251 COLLATE=cp1251_general_ci
ROW_FORMAT=COMPACT;
以及条件查询:
WHERE PROPERTY_3139 IS NULL
我无法更改 table 或查询。但我知道,如果我将 table 分成 2 个分区 - 仅选择可为 null 值的查询将工作得更快。
我可以使用什么样的技巧来做到这一点? NULL 和 NOT NULL 不是范围,我不能将它用作值列表。
PARTITION
可能 无济于事。
NULL
是 INDEX 中的单独值。将 NULL 视为在所有其他值之前存储在 INDEX 中。因此,出于优化目的,IS NULL
和 IS NOT NULL
可以被视为 'range'。
但是...如果超过 20%(10%-30%,取决于月相)的 table 在期望的范围内,优化器将决定它更快进行完整的 table 扫描,而不是在索引和数据之间来回跳转。
回到我的可能...
- 如果少数行有NULL,索引就可以了;分区不会有太大帮助。
- 如果中等数量的行有 NULL,那么 PARTITIONing 可能会有显着的帮助。
- 如果大多数行都为 NULL,则完整 table 扫描几乎与扫描一个分区的所有行一样好。
注意:您不能对多个列进行分区。因此,如果您在 PROPERTY_3139
上进行 PARTITION,则其余属性将不走运。
我有一个 table:
CREATE TABLE `NewTable` (
`IBLOCK_ELEMENT_ID` int(11) NOT NULL ,
`PROPERTY_1836` int(11) NULL DEFAULT NULL ,
`DESCRIPTION_1836` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_1837` int(11) NULL DEFAULT 0 ,
`DESCRIPTION_1837` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_1838` decimal(18,4) NULL DEFAULT NULL ,
`DESCRIPTION_1838` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_3139` int(11) NULL DEFAULT 0 ,
`DESCRIPTION_3139` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
`PROPERTY_3173` decimal(18,4) NULL DEFAULT NULL ,
`DESCRIPTION_3173` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`IBLOCK_ELEMENT_ID`),
INDEX `ix_perf_b_iblock_element_pr_1` (`PROPERTY_1837`) USING BTREE ,
INDEX `ix_perf_b_iblock_element_pr_2` (`PROPERTY_1836`) USING BTREE ,
INDEX `ix_perf_b_iblock_element_pr_3` (`PROPERTY_3139`) USING BTREE
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=cp1251 COLLATE=cp1251_general_ci
ROW_FORMAT=COMPACT;
以及条件查询:
WHERE PROPERTY_3139 IS NULL
我无法更改 table 或查询。但我知道,如果我将 table 分成 2 个分区 - 仅选择可为 null 值的查询将工作得更快。
我可以使用什么样的技巧来做到这一点? NULL 和 NOT NULL 不是范围,我不能将它用作值列表。
PARTITION
可能 无济于事。
NULL
是 INDEX 中的单独值。将 NULL 视为在所有其他值之前存储在 INDEX 中。因此,出于优化目的,IS NULL
和 IS NOT NULL
可以被视为 'range'。
但是...如果超过 20%(10%-30%,取决于月相)的 table 在期望的范围内,优化器将决定它更快进行完整的 table 扫描,而不是在索引和数据之间来回跳转。
回到我的可能...
- 如果少数行有NULL,索引就可以了;分区不会有太大帮助。
- 如果中等数量的行有 NULL,那么 PARTITIONing 可能会有显着的帮助。
- 如果大多数行都为 NULL,则完整 table 扫描几乎与扫描一个分区的所有行一样好。
注意:您不能对多个列进行分区。因此,如果您在 PROPERTY_3139
上进行 PARTITION,则其余属性将不走运。