1

我有一些非常大的桌子——一张大约 200,000,000(扫描),另一张大约 50,000,000(详细信息)。它们通常连接在一组匹配的列上 - 特别是 USPS 条形码数据(zip、zip_4、zip_delivery_point、serial_number)。因为它通常是定位匹配扫描的片段详细记录,所以我想按查找条件对扫描记录进行分区(片段详细记录由代表邮件的一组不同的键分区)。这导致我从自动递增的 PK 转变为 zip、zip_4、zip_delivery_point、serial_number、scan_date_time 的组合。

我现在遇到的问题是优化我的一些大型报告查询。我通常会运行一些脚本来处理数据,包括查找每封邮件的第一次扫描日期、每封邮件的最新扫描日期、计算投递日期等。我经常发现自己需要执行这样的连接:

SELECT a, b, c, s1.first, s2.latest
FROM (subquery to grab MIN() scan record) s1
JOIN _scan s2 ON some_id = (subquery to grab MAX() scan record using fields from s1)

由于我的 PK 没有一个很好的单列,因此我无法以这种方式对记录执行连接,除非我在运行中或预先连接我的复合键值以假冒单列键. 不过,这似乎是多余的。

什么是维护按我当前的复合键排序的记录的物理顺序的好方法,同时还能够加入可以利用先前子查询(在我的示例中为 s1 和 s2)的子查询的结果?

注意:我目前可以通过用子查询替换连接表然后加入该别名来完成正确的结果,但是 mysql 似乎希望在以这种方式执行连接之前将整个表加载到内存中。

表结构

CREATE TABLE `_scan` (
  `facility_zip` varchar(5) NOT NULL,
  `operation_code` varchar(3) NOT NULL,
  `scan_date_time` datetime NOT NULL,
  `zip` varchar(5) NOT NULL DEFAULT '',
  `zip_4` varchar(4) NOT NULL,
  `zip_delivery_point` varchar(2) NOT NULL,
  `barcode_identifier` varchar(2) NOT NULL,
  `service_type` varchar(3) NOT NULL,
  `mailer_id` varchar(9) NOT NULL,
  `serial_number` varchar(9) NOT NULL,
  `new` tinyint(1) NOT NULL DEFAULT '1',
  `first_scan` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`zip`,`zip_4`,`zip_delivery_point`,`serial_number`,`scan_date_time`),
  KEY `operation_code` (`operation_code`)
) ENGINE=InnoDB
/*!50100 PARTITION BY KEY (zip,zip_4,zip_delivery_point,serial_number,scan_date_time)
PARTITIONS 10 */;

CREATE TABLE `_piece_detail` (
  `job_id` varchar(8) NOT NULL,
  `piece_id` bigint(20) NOT NULL,
  `cqt_database_id` int(11) NOT NULL,
  `package_id` int(11) NOT NULL,
  `barcode_identifier` int(11) DEFAULT NULL,
  `service_type` int(11) DEFAULT NULL,
  `mailer_id` varchar(9) DEFAULT NULL,
  `serial_number` varchar(9) NOT NULL,
  `zip` varchar(5) NOT NULL,
  `zip_4` varchar(4) NOT NULL,
  `zip_delivery_point` varchar(2) NOT NULL,
  `est_delivery_date` date DEFAULT NULL,
  `first_scan_date_time` datetime DEFAULT NULL,
  `latest_scan_date_time` datetime DEFAULT NULL,
  PRIMARY KEY (`job_id`,`piece_id`),
  KEY `cqt_database_id` (`cqt_database_id`) USING BTREE,
  KEY `est_delivery_date` (`est_delivery_date`),
  KEY `zip` (`zip`,`zip_4`,`zip_delivery_point`,`serial_number`),
  KEY `first_scan_date_time` (`first_scan_date_time`),
  KEY `latest_scan_date_time` (`latest_scan_date_time`)
) ENGINE=InnoDB
/*!50100 PARTITION BY KEY (job_id,piece_id)
PARTITIONS 10 */;
4

0 回答 0