可以优化此查询或表模式吗?

如何解决可以优化此查询或表模式吗?

我正在运行此过程数百万次,尽管每次都需要花费数毫秒,但最终要花几周的时间才能运行所有这些过程。我想知道是否有人可以帮助我优化或改善其性能。任何改进都可以节省几天!

CREATE PROCEDURE process_parameters(IN parameter1 VARCHAR(128),IN parameter2 VARCHAR(128),IN combination_type CHAR(1))
BEGIN

        SET @parameter1_id := NULL,@parameter2_id := NULL;
        SET @parameter1_hash := "",@parameter2_hash := "";

        IF parameter1 IS NOT NULL THEN

                SET @parameter_hash := parameter1;
                INSERT IGNORE INTO `collection1` (`parameter`) VALUES (parameter1);
                SET @parameter1_id := (SELECT `id` FROM `collection1` WHERE `parameter` = parameter1);

        END IF;

        IF parameter2 IS NOT NULL THEN

                SET @parameter2_hash := parameter2;
                INSERT IGNORE INTO `collection2` (`parameter`) VALUES (parameter2);
                SET @parameter2_id := (SELECT `id` FROM `collection2` WHERE `parameter` = parameter2);

        END IF;

        SET @hash := MD5(CONCAT(@parameter1_hash,@parameter2_hash));
        INSERT IGNORE INTO `combinations` (`hash`,`type`,`parameter1`,`parameter2`) VALUES (@hash,combination_type,@parameter1_id,@parameter2_id);

END

其背后的逻辑是:我将(parameter1,parameter2)的唯一组合存储在combinations中,其中parameter1paramter2可以是NULL(但绝不能两者都与此同时)。我将type存储在combinations中,以便以后知道哪个parameter具有价值。为了确保组合是唯一的,我添加了一个MD5字段(主键(parameter1,parameter2)由于与NULL的比较总是返回NULL而无法工作)。每个parameter都有一个单独的表(分别为collection1collection2)来存储其唯一的id。有成千上万的唯一parameter1parameter2,但是它们的组合被高度重复,并且远低于基数乘法。

例如,("A","1")("A","2")("B",NULL)(NULL,"2")会产生:

`collection1` (`id`,`parameter`)
1,"A"
2,"B"

`collection2` (`id`,"1"
2,"2"

`combinations` (`type`,`parameter2`)
"P1andP2",1,"P1andP2",2,"P1Only",NULL
"P2Only",NULL,2

这些是表的定义:

DESCRIBE `combinations`;
+-------------+-----------------------------------+------+-----+---------+----------------+
| Field       | Type                              | Null | Key | Default | Extra          |
+-------------+-----------------------------------+------+-----+---------+----------------+
| combination | int(11)                           | NO   | PRI | NULL    | auto_increment |
| hash        | char(32)                          | NO   | UNI | NULL    |                |
| type        | enum('P1andP2','P1Only','P2Only') | NO   |     | NULL    |                |
| parameter1  | int(11)                           | YES  |     | NULL    |                |
| parameter2  | int(11)                           | YES  |     | NULL    |                |
+-------------+-----------------------------------+------+-----+---------+----------------+

DESCRIBE `collection1`; (`collection2` is identical)
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| parameter | varchar(255) | NO   | UNI | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

任何帮助将不胜感激!

解决方法

请使用SHOW CREATE TABLE;比DESCRIBE更具描述性。

使用LAST_INSERT_ID()

 SET @parameter1_id := (SELECT `id` FROM `collection1`
                          WHERE `parameter` = parameter1);

可以替换为

 SELECT @parameter1_id := LAST_INSERT_ID();

这将避免往返服务器。

糟糕... OP指出如果该行是dup,则不会返回ID。这是一种可能运行速度更快的解决方法:

INSERT INTO `collection1` (`parameter`)
        VALUES (parameter1)
    ON DUPLICATE KEY UPDATE
        id = LAST_INSERT_ID(id);
SELECT @parameter1 := LAST_INSERT_ID(id);

这是一个笨拙的把戏,在文档中的某个地方进行了记录。但;下面更多...

收缩表

  • 您真的需要combination吗?您还有另一个UNIQUE键可以用作PRIMARY KEY。这可能会减少最后INSERT所花费的时间。

  • 这可能会(或可能不会)加快速度,但仅是因为行大小缩小了:与其将md5存储到CHAR(32)中,不如将UNHEX(md5)存储到BINARY(16)中。 / p>

批量插入

您能一次将一堆东西收集到INSERT吗?如果您收集1000行并将它们放入单个INSERT(实际上是3 INSERTs,因为涉及到3个表),则它的运行速度实际上是原来的10倍。

由于需要ID,因此变得更加复杂。您需要将事物分为collection1collection2然后combinations上工作。

由于“ combination *”表本质上是“规范化”的表,请参见我关于如何非常有效地对其进行批处理的讨论:http://mysql.rjweb.org/doc.php/staging_table#normalization它涉及2条语句,其中一条用于插入新行,另一条用于获取所有id。批处理。

凉爽

完全摆脱@parameter*_hash@hash。将@hash调用的使用更改为:

INSERT IGNORE INTO combinations (...) VALUES
    ( CONCAT(COALESCE(parameter1,''),COALESCE(parameter2,'')),...)

这样想吧...每个语句花费不小的时间。 (这在插入的批处理中显着显示。)由于增加了一条语句的复杂性,我付出了一些代价摆脱了4条语句。

设置

最重要的可能是innodb_flush_log_at_trx_commit = 2

3个流

编写3个过程,每个过程都将代码简化为特定的type。将此与批处理结合起来可以进一步加快速度。

潜在问题

  • 我认为这两个人将获得相同的hash。因此,这两个只有一行:

      ("xyz",NULL)
      (NULL,"xyz")
    
  • 请注意,如果已经存在具有给定唯一键的行,则INSERT IGNORE将刻录id。因此,请密切注意INT(只有20亿)的价值用尽。更改为INT UNSIGNED会将其提高到4B,仍然为4个字节。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-