【问题标题】:Query from 3 tables, lasts forever从 3 个表查询,永远持续
【发布时间】:2019-08-12 21:27:34
【问题描述】:

我在Ubuntu 18.04. 上使用mysql-workbench 6.3

我创建了三个表,如下所示:

CREATE TABLE `prefix_random` (
  `domain` varchar(500) NOT NULL,
   PRIMARY KEY (`domain`),
   UNIQUE KEY `domain_UNIQUE` (`domain`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1

注意:还有额外的 32 个字段,但我不查询它们,为简洁起见省略。

例子:

domain
-----------------
sub.example.net

第二张桌子:

CREATE TABLE `noprefix_random` (
  `domain` varchar(500) NOT NULL,
  PRIMARY KEY (`domain`),
  UNIQUE KEY `domain_UNIQUE` (`domain`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

注意:还有额外的 32 个字段,但我不查询它们,为简洁起见省略。

例子:

domain
----------------------
example.net

第三张表:

CREATE TABLE `new_random` (
  `new_domain` varchar(500) NOT NULL,
  PRIMARY KEY (`new_domain`),
  UNIQUE KEY `new_domain_UNIQUE` (`new_domain`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

注意:还有额外的 3 个字段,但我没有查询它们,为简洁起见省略。

例子:

new_domain
------------------------
http://sub.example.com

我要查询三个表中的共享名example.com,如下:

查询:

SELECT `new_random`.`new_domain`,`prefix_random`.`domain`,`noprefix_random`.`domain`
FROM `myscheme`.`new_random`
JOIN `myscheme`.`prefix_random`
# the substring to extract the part: sub.example.com
ON substring_index(`new_random`.`new_domain`,'http://',-1) = `prefix_random`.`domain`
JOIN `myscheme`.`noprefix_random`
# by adding sub, it becomes: sub.example
ON CONCAT('sub.',`noprefix_random`.`domain`) = `new_domain`,`prefix_random`; 

预期的输出是:

http://sub.example.com, sub.example.com, example.com

查询永远持续。如果我使用 L

将输出限制为少量
LIMIT 10;

我得到了结果。记录数不会太大。 prefix_random 包含 620062、noprefix_random 包含 62294 和 588380 条记录。

有什么问题?你能帮我运行查询吗?

【问题讨论】:

  • 注意,主键是 a) 键和 b) 总是唯一的。不需要在其上使用辅助键。
  • 我的每个表都有一个主键。你想指出什么?对不起,我没有明白你的意思。
  • 您不需要 xxx_UNIQUE 键,因为同一个字段是主键。
  • @danblack 这没有害处。有什么问题?

标签: mysql database relational-database mysql-workbench database-performance


【解决方案1】:

处理域的最佳方法是使用具有reverse 函数的generated columns 并索引此生成的列。这样,大量查询可以WHERE domain LIKE CONCAT(reverse(const),'%') 并使用索引。

在查询中删除http:// 也是一种昂贵的方法。也可以在生成的函数/索引中使用它。

 CREATE TABLE `new_random` (
   `new_domain` varchar(500) NOT NULL,
   PRIMARY KEY (`new_domain`))

 INSERT INTO new_random VALUES ('http://a.b.c'),('http://d.e.f')

 ALTER TABLE new_random ADD no_https VARCHAR(500) AS (substring_index(`new_domain`,'http://',-1)), ADD KEY(no_https)

 ALTER TABLE new_random ADD rev_domain VARCHAR(500) AS (REVERSE(no_https)), ADD KEY(rev_domain)


 SELECT * FROM new_random
新域 | no_https | rev_domain :----------- | :------- | :--------- http://a.b.c | a.b.c | c.b.a http://d.e.f | d.e.f | f.e.d
 EXPLAIN SELECT new_domain FROM new_random WHERE rev_domain LIKE 'c.b.%'
编号 |选择类型 |表|隔断 |类型 |可能的键 |关键 | key_len |参考 |行 |过滤 |额外的 -: | :------------ | :--------- | :--------- | :---- | :------------ | :--------- | :-------- | :--- | ---: | --------: | :------------------------ 1 |简单 |新随机 | |范围 | rev_domain | rev_domain | 2003 | | 1 | 100.00 |使用哪里;使用索引

db小提琴here

【讨论】:

  • 谢谢。您能否提供详细语法的完整答案?
  • 最好的新方法是在 MySQL 8.0.13 或 14+ 中,顺便支持对表达式或函数进行索引。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 2014-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多