mysql - SQL 查询优化 select 或 inner join

标签 mysql sql

您好,我的一个请求很慢,时间很长。 我测试使用 INDEX,没有结果。 我被建议放置内部连接而不是我的选择,但我不知道如何在同一张表上进行不同的操作。

表格:

 CREATE TABLE `cryptos` (
  `uuid` char(36) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `shortname` varchar(255) DEFAULT NULL,
  [...]
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `cryptos_infos` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
 [...]
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  `fk_cryptoid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_cryptoid` (`fk_cryptoid`),
  CONSTRAINT `cryptos_infos_ibfk_1` FOREIGN KEY (`fk_cryptoid`) REFERENCES `cryptos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `eventcryptorelations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  [...]
  `fk_cryptoid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  `fk_eventid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_cryptoid` (`fk_cryptoid`),
  KEY `fk_eventid` (`fk_eventid`),
  CONSTRAINT `eventcryptorelations_ibfk_1` FOREIGN KEY (`fk_cryptoid`) REFERENCES `cryptos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `eventcryptorelations_ibfk_2` FOREIGN KEY (`fk_eventid`) REFERENCES `events` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `events` (
  `uuid` char(36) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `title` varchar(255) DEFAULT NULL,
  [...]
  PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `github_activ_repos` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  [...]
  `fk_githubid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_githubid` (`fk_githubid`),
  CONSTRAINT `github_activ_repos_ibfk_1` FOREIGN KEY (`fk_githubid`) REFERENCES `github_info_repos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `github_info_repos` (
  `uuid` char(36) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `idgit` int(11) DEFAULT NULL,
  [...]
  `fk_cryptoid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`uuid`),
  KEY `fk_cryptoid` (`fk_cryptoid`),
  CONSTRAINT `github_info_repos_ibfk_1` FOREIGN KEY (`fk_cryptoid`) REFERENCES `cryptos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `prices` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `open` double DEFAULT NULL,
  [...]
  `date` datetime DEFAULT NULL,
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  `fk_cryptoid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_cryptoid` (`fk_cryptoid`),
  CONSTRAINT `prices_ibfk_1` FOREIGN KEY (`fk_cryptoid`) REFERENCES `cryptos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `trendsSearches` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `time` datetime DEFAULT NULL,
  `formattedTime` varchar(255) DEFAULT NULL,
  `value` float DEFAULT NULL,
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  `fk_cryptoid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_cryptoid` (`fk_cryptoid`),
  CONSTRAINT `trendsSearches_ibfk_1` FOREIGN KEY (`fk_cryptoid`) REFERENCES `cryptos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `twitter_activs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  [...]
  `fk_twitterid` double DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_twitterid` (`fk_twitterid`),
  CONSTRAINT `twitter_activs_ibfk_1` FOREIGN KEY (`fk_twitterid`) REFERENCES `twitter_infos` (`idtwitter`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `twitter_infos` (
  `idtwitter` double NOT NULL,
 [...]
  `fk_cryptoid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`idtwitter`),
  KEY `fk_cryptoid` (`fk_cryptoid`),
  CONSTRAINT `twitter_infos_ibfk_1` FOREIGN KEY (`fk_cryptoid`) REFERENCES `cryptos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `volumes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `volumefrom` double DEFAULT NULL,
  [...]
  `fk_cryptoid` char(36) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_cryptoid` (`fk_cryptoid`),
  CONSTRAINT `volumes_ibfk_1` FOREIGN KEY (`fk_cryptoid`) REFERENCES `cryptos` (`uuid`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

为了更好地理解,我缩小了表格。

查询说明:

我需要按 cryptos_info 表中的“排名”字段排序前 100 个条目。 以最新入场价和24小时前的价格。 与其他表上的其他信息,例如卷上的条目,在表 github ....

查询:

select cryptos_infos.rank, cryptos.shortname, cryptos.imageurl, cryptos_infos.coinminde,
(SELECT open FROM prices WHERE prices.fk_cryptoid = cryptos.uuid and prices.date LIKE '2018-09-16%' order by prices.date DESC limit 1) as priceone,
 (SELECT open FROM prices WHERE prices.fk_cryptoid = cryptos.uuid and prices.date LIKE '2018-09-16%' order by prices.date DESC limit 1) as pricetwo , 
(SELECT P.open FROM prices P WHERE P.fk_cryptoid = cryptos.uuid order by P.createdAt DESC limit 1) as open,
 (select count(E.hot) from events E where E.uuid in (select EC.fk_eventid from eventcryptorelations EC where EC.fk_cryptoid = cryptos.uuid) and E.hot = 1) as hot,
 (SELECT value FROM trendsSearches WHERE trendsSearches.fk_cryptoid = cryptos.uuid order by trendsSearches.time DESC limit 1) as trenone,
 (SELECT value FROM trendsSearches WHERE trendsSearches.fk_cryptoid = cryptos.uuid  order by trendsSearches.time DESC LIMIT 1,1) as trentwo,
 (select GAR.stars from github_activ_repos GAR where GAR.fk_githubid = ( select uuid from github_info_repos GIR, github_activ_repos GR where GIR.fk_cryptoid = cryptos.uuid and GIR.uuid = GR.fk_githubid order by GR.stars DESC limit 1) order by GAR.time DESC limit 1) as gitone, 
(select GAR.stars from github_activ_repos GAR where GAR.fk_githubid = ( select uuid from github_info_repos GIR, github_activ_repos GR where GIR.fk_cryptoid = cryptos.uuid and GIR.uuid = GR.fk_githubid order by GR.stars DESC limit 1) order by GAR.time DESC limit 1,1) as gittwo,
 (SELECT abonnees FROM twitter_activs WHERE twitter_activs.fk_twitterid = (select idtwitter from twitter_infos where twitter_infos.fk_cryptoid = cryptos.uuid) and twitter_activs.createdAt LIKE '2018-09-16%' order by twitter_activs.createdAt DESC limit 1) as abotone, 
(SELECT abonnees FROM twitter_activs WHERE twitter_activs.fk_twitterid = (select idtwitter from twitter_infos where twitter_infos.fk_cryptoid = cryptos.uuid) and twitter_activs.createdAt LIKE '2018-09-16%' order by twitter_activs.createdAt DESC limit 1) as abottwo 
from cryptos, cryptos_infos where cryptos.uuid = cryptos_infos.fk_cryptoid and cryptos_infos.rank is not null  order by cryptos_infos.rank ASC limit 100;

信息: 所有请求 = 30s

请求 - 选择表格价格 = 1.23s

出现慢问题的线路:

(SELECT open FROM prices WHERE prices.fk_cryptoid = cryptos.uuid and prices.date LIKE '2018-09-23%' order by prices.date DESC limit 1) as priceone,
 (SELECT open FROM prices WHERE prices.fk_cryptoid = cryptos.uuid and prices.date LIKE '2018-09-23%' order by prices.date DESC limit 1) as pricetwo , 
(SELECT P.open FROM prices P WHERE P.fk_cryptoid = cryptos.uuid order by P.createdAt DESC limit 1) as open,

最佳答案

首先,不要对日期使用like。相反:

(SELECT open FROM prices p WHERE p.fk_cryptoid = cryptos.uuid and p.date >= '2018-09-23' AND p.date < '2018-09-24' order by p.date DESC limit 1) as priceone,
(SELECT open FROM prices p WHERE p.fk_cryptoid = cryptos.uuid and p.date >= '2018-09-23' AND p.date < '2018-09-24' order by p.date DESC limit 1) as pricetwo , 
(SELECT P.open FROM prices P WHERE P.fk_cryptoid = cryptos.uuid order by P.createdAt DESC limit 1) as open,

为此,您可以尝试在 prices(fk_cryptoid, p.date, open)prices(fk_cryptoid, createdAt, open) 上建立索引。

你可能需要更激烈一点。目标是为子查询使用索引。我不确定 MySQL 是否足够聪明,可以在这些情况下做到这一点。

您可能需要将现有的 date 列更改为只是一个日期,并添加一个包含日期/时间(或只是一个时间列)的新日期时间列。然后您可以将子查询表述为:

(SELECT open FROM prices p WHERE p.fk_cryptoid = cryptos.uuid and p.date = '2018-09-23' order by p.datetime DESC limit 1) as priceone,

你想要的索引在 (fk_cryptoid, date, datetime, open) 上。

关于mysql - SQL 查询优化 select 或 inner join,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52466280/

相关文章:

java - Java 类中的 SQL 代码

php - Paypal Webhook 响应

sql - 将前 1000 条记录从 csv 文件导入到 sql server

javascript - 链式选择框(国家、州、城市)

c# - 直接从 C# 连接对象中提取 MySql 连接 ID

mysql - 模拟MySql 5.7删除查询

where子句中的MySQL未知列?

php - 尝试使用 PHP 创建注册表单

mysql - 提高 MySQL 查询的性能

mysql - 数据库设计,列数可变