mariadb 虚拟机内的选择SQL查询非常慢

k75qkfdt  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(153)

我们开发了一个使用MariaDB服务器的后端应用程序。为了进行部署,后端在Docker容器中运行,MariaDB服务器在另一个Docker容器中运行(使用官方映像)。我们建立了一个Docker Compose项目,一切都运行正常。
但是,如果我们使用Docker容器在虚拟机(基于Kubuntu或Lubuntu)中部署应用程序,一些选择SQL查询在主机上运行不到一秒,但却永远无法运行。
主机有SSD存储,8个内核和32GB或RAM。虚拟机是用4个内核和20GB RAM创建的。似乎在虚拟机上使用更多内核或RAM并没有任何区别,我们想知道是什么原因导致了这种真正的低性能。任何想法都是赞赏的,因为我们已经尝试了很多事情都没有成功。
查询:

select  distinct gene1_.id as id1_6_, gene1_.defaultName as defaultN2_6_,
        gene1_.species as species3_6_
    from  gene_in_interactome geneininte0_
    inner join  gene gene1_  ON geneininte0_.gene=gene1_.id
    inner join  gene_name names2_  ON gene1_.id=names2_.geneId
    inner join  gene_name_value names3_  ON names2_.geneId=names3_.geneId
      and  names2_.source=names3_.geneSource
    where  (geneininte0_.interactome in (666))
      and  (cast(gene1_.id as char) like 'arg%'
              or  names3_.name like 'arg%'
           )
    order by  gene1_.id asc
    limit  10

我已经确定关键部分是(cast(gene1_.id as char) like 'arg%' or names3_.name like 'arg%'),因为names3_需要最后一个内部连接。
下面是创建表:

gene_in_interactome | CREATE TABLE `gene_in_interactome` (
  `gene` int(11) NOT NULL,
  `interactome` int(11) NOT NULL,
  `species` int(11) NOT NULL,
  PRIMARY KEY (`gene`,`interactome`,`species`),
  KEY `FKsswgs3cc7avkugqvq78sv21xg` (`interactome`),
  KEY `FKtpcnom6fs9jal4qfgao444cse` (`species`),
  CONSTRAINT `FKa02a13n65pbhq1m1ehk63f4es` FOREIGN KEY (`gene`) REFERENCES `gene` (`id`),
  CONSTRAINT `FKsswgs3cc7avkugqvq78sv21xg` FOREIGN KEY (`interactome`) REFERENCES `interactome` (`id`),
  CONSTRAINT `FKtpcnom6fs9jal4qfgao444cse` FOREIGN KEY (`species`) REFERENCES `species` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 |

| gene  | CREATE TABLE `gene` (
  `id` int(11) NOT NULL,
  `defaultName` varchar(255) NOT NULL,
  `species` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `IDXnkshoslla6kq08gqh38grefke` (`id`,`species`),
  KEY `FKg5uaph3wq3eu765ch9lkq6qi1` (`species`),
  CONSTRAINT `FKg5uaph3wq3eu765ch9lkq6qi1` FOREIGN KEY (`species`) REFERENCES `species` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 |

| gene_name | CREATE TABLE `gene_name` (
  `geneId` int(11) NOT NULL,
  `source` varchar(255) NOT NULL,
  PRIMARY KEY (`geneId`,`source`),
  CONSTRAINT `FKltnrhrbud9fvdilc74lybdvio` FOREIGN KEY (`geneId`) REFERENCES `gene` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 |

| gene_name_value | CREATE TABLE `gene_name_value` (
  `geneId` int(11) NOT NULL,
  `geneSource` varchar(255) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  KEY `FK_gene_name_gene_name_values` (`geneId`,`geneSource`),
  CONSTRAINT `FK_gene_name_gene_name_values` FOREIGN KEY (`geneId`, `geneSource`) REFERENCES `gene_name` (`geneId`, `source`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 |
7dl7o3gd

7dl7o3gd1#

cast(gene1_.id as char) like 'arg%'
              or  names3_.name like 'arg%'

“arg”是来自用户的值吗?请注意SQL注入。
ORCAST都可能会严重影响性能。通过检查“arg”是否为数字,以编程方式生成查询;如果是,则使用

WHERE id = 'arg'

如果没有,则使用

WHERE name LIKE 'arg%'

与此同时,以下一些索引可能会有所帮助:

geneininte0_:  INDEX(interactome, gene)
names3_:  INDEX(name, geneId,  geneSource)

当添加复合索引时,DROP具有相同前导列的索引。也就是说,当同时具有INDEX(a)和INDEX(a,b)时,丢弃前者。
gene_name的列数是否多于2列?如果不是,为什么存在?

KEY(id, species)

由于idPRIMARY KEY,它与数据“聚簇”在一起,因此该索引基本上是无用的。

相关问题