我有一个长期运行的MySQL查询,它从一个表中的相应记录更新另一个表中的记录.在这种情况下,将派生的商户分配记录中的字段设置到原始交易记录中:


update transaction t
        inner join assignment a on a.transaction_id = t.id
    set
        t.merchant_name = a.name,
        t.merchant_org_id = a.merchant_org_id,
        t.category_id = a.category_id
        t.assignment_pending = false
        where t.id in ('...', '...', '...')

此查询正在进行...很长一段时间.我有一份作业(job)transaction_id栏的索引...但是,有没有其他方法来优化这个查询呢?

以下是相关方案和解释方案:

CREATE TABLE `transaction` (
  `id` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  `org_id` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  `service_connection_id` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
  `amount` bigint NOT NULL,
  `currency_code` varchar(3) NOT NULL,
  `amount_usd` bigint NOT NULL DEFAULT '0',
  `merchant_name` varchar(255) NOT NULL,
  `mcc` char(4) DEFAULT NULL,
  `transaction_type` varchar(255) NOT NULL,
  `category_id` char(36) NOT NULL,
  `merchant_org_id` char(36) DEFAULT NULL,
  `user_id` char(36) DEFAULT NULL,
  `mask` varchar(255) DEFAULT NULL,
  `assignment_pending` tinyint(1) NOT NULL DEFAULT '0',
  `state` varchar(255) NOT NULL DEFAULT 'posted',
  `assignment_id` varchar(255) DEFAULT NULL,
  `epoch_authorized` bigint NOT NULL DEFAULT '0',
  `epoch_posted` bigint DEFAULT NULL,
  `raw_description` varchar(255) NOT NULL DEFAULT '',
  `created` bigint NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_provider_tx_id` (`org_id`,`provider_tx_id`),
  KEY `idx_tx_merchant` (`merchant_org_id`),
  KEY `idx_tx_assignment` (`assignment_id`),
  KEY `idx_tx_org_authorized` (`org_id`,`epoch_authorized`),
  KEY `idx_tx_org_posted` (`org_id`,`epoch_posted`),
  KEY `idx_tx_org_merchant` (`org_id`,`merchant_org_id`),
  KEY `idx_tx_org_amount_usd` (`org_id`,`amount_usd`),
  KEY `idx_tx_assignment_pending` (`org_id`,`assignment_pending`,`epoch_authorized`,`id`),
  KEY `idx_tx_org_vendor_by_range` (`org_id`,`merchant_org_id`,`epoch_authorized`)
)

CREATE TABLE `assignment` (
  `id` char(36) NOT NULL,
  `org_id` char(36) NOT NULL,
  `user_id` char(36) DEFAULT NULL,
  `name` varchar(255) NOT NULL,
  `date` date DEFAULT NULL,
  `factor_id` char(36) DEFAULT NULL,
  `merchant_org_id` char(36) DEFAULT NULL,
  `category_id` char(36) NOT NULL,
  `transaction_id` char(36) DEFAULT NULL,
  `assignment_method` varchar(255) NOT NULL,
  `created` bigint NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_assignment_transaction` (`transaction_id`),
  KEY `idx_org` (`org_id`),
  KEY `idx_user` (`user_id`),
  KEY `idx_date` (`date`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Explain Plan

ID 1
Select type UPDATE
Table t
Matching partitions
Join type const
Chosen index PRIMARY
Chosen index length 144
Compared columns const
Rows filtered 100%
Query cost 0
Additional information
ID 1
Select type SIMPLE
Table a
Matching partitions
Join type range
Chosen index idx_assignment_transaction
Chosen index length 145
Compared columns
Rows filtered 100%
Query cost 0
Additional information Using where

推荐答案

@ErsterBasha猜对了.The problem was the collation.作为背景,我不使用外键作为应用程序的原因(在批量创建记录时不愿考虑排序),所以这可能就是我在这种情况下结束的原因.

在确保ID字段以与其对应的键列相同的方式正确排序后,UPDATE查询从几十秒减少到几分之一秒.


-- Example of manually setting the collation method on the desired columns

ALTER TABLE transaction MODIFY COLUMN id CHAR(36) NOT NULL COLLATE utf8mb4_bin;
ALTER TABLE transaction MODIFY COLUMN assignment_id CHAR(36) NULL COLLATE utf8mb4_bin;
ALTER TABLE assignment MODIFY COLUMN id CHAR(36) NOT NULL COLLATE utf8mb4_bin;
ALTER TABLE assignment MODIFY COLUMN transaction_id CHAR(36) NULL COLLATE utf8mb4_bin;

Mysql相关问答推荐

客户跨订阅的跨时间线计数

在联合查询中使用GROUP BY和ORDER BY

MySQL RDS ALTER TABLE ENUM短暂中断了我的数据库连接

使用MySQL工作台导出具有数据的数据库表并导入到其字段具有不同数据类型的同一表中

了解MySQL_stmt_BIND_NAMED_Param()-MySQL C API

插入时发生日期时间字段溢出错误

JPA对具有动态键和动态值的JSON列的原生查询

MySQL工作台的编码问题

为什么 MAX 函数通过调用在 group 中生成正确的结果

是否可以使用以EXPLAIN EXTENDED ...开头的 SQL 语句修改数据?

创建表时我的 SQL 语句有什么问题

使用数据表的直方图(SQL 查询)

如何在 Mysql 中创建复合外键

PDO:MySQL 服务器已消失

将 MySQL 数据库置于版本控制之下?

我可以在单个 Amazon RDS 实例上创建多少个数据库

启用 NO_BACKSLASH_ESCAPES 选项时如何转义文字百分号?

MySQL查询/子句执行顺序

更改 Laravel 的 created_at 和 updated_at 的名称

什么是mysql的BETWEEN性能超过..?