我有以下左外部联接查询:
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 |
+-------+-----------+
3条答案
按热度按时间wfauudbj1#
我认为你过分夸大了你的解释和你想要得到的东西。如果我对你的问题的解释是正确的,你需要左连接。不管右边是什么,您都需要从左边的表中选择,但是如果右边恰好符合您的条件,那么根据需要获取条目。
您的查询将条件应用于相同的左表字段,而不是左表字段和右表字段。
为了在连接到包含60(或更多)列的右侧表时帮助优化查询,但您只是比较fk\u id及其“job\u details”(根据测试人员和开发人员的查询示例),我将仅在这两列上构建一个复合索引,以便对其进行优化,以便在(fk\u id,job\u details)上进行连接和搜索…索引。这样,引擎就可以直接从索引中得到答案,而不必返回到所有60列都存在的原始数据页。表\u left上还应该有一个复合索引(pk \u id,name)用于优化。
现在,基于“%somevalue%”进行搜索时,需要进行全文搜索,因为前导“%”意味着只要搜索字符串在查询中的某个位置,就不知道字符串前面有多少个字符,后面有多少个字符。除非您需要,否则我建议不要使用前导“%”,但这是您的选择。
因此,这将为您提供基于左表(名称为“tester”)或右表(作业详细信息为“tester”)的信息。但我不认为这是最佳的。
但是,我实际上建议在(job\u details,fk\u id)上提供一个不同的索引,然后使用distinct执行联合查询。
这样,在按名称查找时,左表将针对其distinct进行优化,右表将通过搜索其jobdetails并获取相应的左表名称信息进行优化。
ma8fv8wu2#
如果您需要返回表\u left中的所有结果(不管它是否匹配),那么left join是正确的,就像您正在做的那样,所以不要担心尝试切换它。
查询大约需要1分钟,我认为这是因为它在所有列上执行完全的外部联接。我不需要所有的专栏。
让我们明确一点:联接只对联接条件中列出的列进行操作:在本例中,表\u right.fk\u id和表\u left.pk\u id。但是,非常大的表需要更长的时间来处理,这是正确的。如果不需要其余的列,最好在执行任何联接之前将它们排除在外,因为输出表的宽度将减小(这意味着返回该输出表时的速度会提高)。
当试图提高连接性能时,mysql的经验法则是使用索引。用外行的话说,索引基本上告诉数据库使用特定的列作为表的查找。在我添加了一个索引之后,速度的提高让我大吃一惊。
我强烈建议在这种情况下使用索引。这里有一个伟大的教程设置这些。祝你好运!
rkkpypqq3#
左连接很好:
查询大约需要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匹配的行。