当我只需要where子句中joined(right)表中的一列时,是否需要左外连接?

eufgjt7s  于 2021-06-18  发布在  Mysql
关注(0)|答案(3)|浏览(486)

我有以下左外部联接查询:

SELECT table_left.pk_id, table_left.name
FROM table_left left outer join table_right on table_right.fk_id = table_left.pk_id
WHERE table_right.name like '%entered search value%'

我的问题是表\u right有超过1000000行和超过60列。查询大约需要1分钟,我认为这是因为它在所有列上执行完全的外部联接。我不需要所有的专栏。我只需要使用一列(table\u right.fk\u id),这样就可以在where子句中连接两个表和另一列(table\u right.name)。
我使用外部联接是因为我需要在表\u left中包含在表\u right中没有行的结果。
任何有助于提高上述查询速度的建议都将不胜感激。
下面是我的两个表的示例:

+-------------------+
| table_left        |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 1     | IBM       |
+-------+-----------+
| 2     | Facebook  |
+-------+-----------+
| 3     | Google    |
+-------+-----------+
| 4     | Microsoft |
+-------+-----------+

+--------------------------------------------+
| table_right                                |
+--------------------------------------------+
| table_right_pk_id | fk_id | job_details    |
+-------------------+-------+----------------+
| 1                 | 1     | Tester         |
+-------------------+-------+----------------+
| 2                 | 2     | Toilet Cleaner |
+-------------------+-------+----------------+
| 3                 | 2     | Secretary      |
+-------------------+-------+----------------+
| 4                 | 3     | Developer      |
+-------------------+-------+----------------+

我想能够搜索'姓名'(在表左)和'工作详细信息'(在表右),但使用表左列。这是我提出的查询,查询下面是一些预期结果:

SELECT table_left.pk_id, table_left.name
FROM table_left left outer join table_right on table_right.fk_id = table_left.pk_id
WHERE table_right.name LIKE '%searchTerm%' OR table_left.name LIKE '%searchTerm%'

例1
searchterm='ibm'
结果:

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 1     | IBM       |
+-------+-----------+

例2
searchterm='测试仪'
结果:

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 1     | IBM       |
+-------+-----------+

例3
searchterm='微软'
结果:(即使表\u right中没有记录,仍应返回microsoft)

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 4     | Microsoft |
+-------+-----------+

例4
searchterm='开发者'
结果:

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 2     | Facebook  |
+-------+-----------+
wfauudbj

wfauudbj1#

我认为你过分夸大了你的解释和你想要得到的东西。如果我对你的问题的解释是正确的,你需要左连接。不管右边是什么,您都需要从左边的表中选择,但是如果右边恰好符合您的条件,那么根据需要获取条目。
您的查询将条件应用于相同的左表字段,而不是左表字段和右表字段。
为了在连接到包含60(或更多)列的右侧表时帮助优化查询,但您只是比较fk\u id及其“job\u details”(根据测试人员和开发人员的查询示例),我将仅在这两列上构建一个复合索引,以便对其进行优化,以便在(fk\u id,job\u details)上进行连接和搜索…索引。这样,引擎就可以直接从索引中得到答案,而不必返回到所有60列都存在的原始数据页。表\u left上还应该有一个复合索引(pk \u id,name)用于优化。
现在,基于“%somevalue%”进行搜索时,需要进行全文搜索,因为前导“%”意味着只要搜索字符串在查询中的某个位置,就不知道字符串前面有多少个字符,后面有多少个字符。除非您需要,否则我建议不要使用前导“%”,但这是您的选择。

select
      LT.PKID,
      LT.Name
   from
      Table_Left LT
         LEFT JOIN Table_Right RT
            on LT.PK_ID = RT.FK_ID
           AND RT.JOB_Details LIKE 'Tester%'
   where
         LT.Name Like 'Tester%'
      OR NOT RT.FK_ID IS NULL

因此,这将为您提供基于左表(名称为“tester”)或右表(作业详细信息为“tester”)的信息。但我不认为这是最佳的。
但是,我实际上建议在(job\u details,fk\u id)上提供一个不同的索引,然后使用distinct执行联合查询。

select DISTINCT
      LT.PKID,
      LT.Name
   from
      Table_Left LT
   where
      LT.Name Like 'Tester%'
UNION
select 
      LT.PKID,
      LT.Name
   FROM
      Table_Right RT
         JOIN Table_Left LT
            on RT.FK_ID = LT.PK_ID
   where 
      RT.JOB_Details LIKE 'Tester%'

这样,在按名称查找时,左表将针对其distinct进行优化,右表将通过搜索其jobdetails并获取相应的左表名称信息进行优化。

ma8fv8wu

ma8fv8wu2#

如果您需要返回表\u left中的所有结果(不管它是否匹配),那么left join是正确的,就像您正在做的那样,所以不要担心尝试切换它。
查询大约需要1分钟,我认为这是因为它在所有列上执行完全的外部联接。我不需要所有的专栏。
让我们明确一点:联接只对联接条件中列出的列进行操作:在本例中,表\u right.fk\u id和表\u left.pk\u id。但是,非常大的表需要更长的时间来处理,这是正确的。如果不需要其余的列,最好在执行任何联接之前将它们排除在外,因为输出表的宽度将减小(这意味着返回该输出表时的速度会提高)。
当试图提高连接性能时,mysql的经验法则是使用索引。用外行的话说,索引基本上告诉数据库使用特定的列作为表的查找。在我添加了一个索引之后,速度的提高让我大吃一惊。
我强烈建议在这种情况下使用索引。这里有一个伟大的教程设置这些。祝你好运!

rkkpypqq

rkkpypqq3#

左连接很好:

SELECT table_left.pk_id, table_left.name
FROM table_left 
LEFT JOIN table_right on table_right.fk_id = table_left.pk_id
WHERE table_right.name LIKE '%searchTerm%' OR table_left.name LIKE '%searchTerm%'

查询大约需要1分钟
该性能问题与联接类型无关。
很可能是“双端”通配符导致了较长的查询时间。使用索引不会改善这些问题。你的经验法则:
使用相等优先于喜欢
优先使用like'something%'而不是like'%something'
优先使用like“%something”而不是like“%something%
如果你使用像“%something%”,不要期望 lightning 般的响应时间
说真的,您需要重新考虑使用通配符来提高性能。可以使用尾随通配符获得对查询的索引支持,如果在列的反面构建索引,则可以获得对前导通配符的索引支持,但需要全文索引(以及不同的查询)才能获得对(相当于)双端通配符的任何索引支持。
以前:
我使用外部联接是因为我需要在表\u left中包含在表\u right中没有行的结果。
如果您只是通过 WHERE table_right.name like '%entered search value%' where子句只能返回从表\u right到表\u left匹配的行。

相关问题