SQL查询优化选择或内部联接

时间:2018-09-23 12:54:40

标签: 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表上的“ rank”字段排序的前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;

信息: 所有请求= 30秒

请求-选择价格= 1.23秒

行慢的地方:

(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,

1 个答案:

答案 0 :(得分:0)

首先,请勿使用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列更改为一个日期,并添加一个同时包含日期/时间(或仅是时间列)的新的datetime列。然后,您可以将子查询的短语设置为:

(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)上。

相关问题