【问题标题】:mysql searching in various fields with OR performing full table scanmysql 在各个字段中搜索 OR 执行全表扫描
【发布时间】:2013-02-13 06:36:19
【问题描述】:

我有 3 个表(不写所有和实际的字段名称)

  • 合同(约 30 000 行)

    |id|client_id|contract_nr|....

  • 容器(~30 000 行

    |id|contract_nr|phone_1(varchar)|....

  • 客户端(~35 000 行)

    |id|phone_2(varchar)|phone_3(varchar)|phone_4(varchar)|....

我需要搜索电话号码,所以我试试这个 - 如果我搜索一个电话号码,例如在 container.phone_1 中

SELECT *
FROM contract JOIN client
     ON contract.client_id = client.id
     JOIN container
     ON contract.contract_nr = container.contract_nr
WHERE container.phone_1 LIKE '264%' 

id  select_type table   type    possible_keys   key key_len ref rows    filtered    Extra
-------------------------------------------------------------------------------------------------------------
1   SIMPLE  container   range   contract_nr,phone_1 phone_1 63  NULL    912 100.00  Using where
1   SIMPLE  contract    ref contract_nr,client_id   contract_nr 26  container.contract_nr   1   100.00  
1   SIMPLE  client  eq_ref  PRIMARY,id  PRIMARY 3   contract.client_id  1   100.00  

但是当我开始使用 OR 从客户端添加电话号码时

SELECT * 
FROM contract JOIN client 
    ON contract.client_id = client.id 
    JOIN container ON contract.contract_nr = container.contract_nr 
WHERE (
    container.phone_1 LIKE '264%' OR 
    client.phone_2 LIKE '264%' OR 
    client_phone_3 LIKE '264%'
)

解释扩展:

id  select_type table   type    possible_keys   key key_len ref rows     filtered   Extra
-------------------------------------------------------------------------------------------------------------
1   SIMPLE  container   ALL k_ligums,k_telef    NULL    NULL    NULL    32113   100.00  
1   SIMPLE  contract    ref contract_nr,client_id   contract_nr 26  za.zaao_konteineri.k_ligums 1   100.00  
1   SIMPLE  client  eq_ref  PRIMARY,id  PRIMARY 3   contract.client_id  1   100.00  Using where

我已经索引了所有用于连接表和用于搜索的字段。 我还尝试为包含所有搜索行的客户端和容器表创建多列索引 - 没有区别。

如何避免扫描容器表的 32113 行?

【问题讨论】:

  • 连接会影响大型数据集中的查询性能。如果可能,请考虑避免使用它们,或者如果您需要大规模处理数据,请考虑重组数据
  • 当我在查询中添加“OR”时,问题就开始了——直到那时,连接都没有问题!将连接替换为 table1.field = table2.field - 没有区别 - 仍然执行全扫描!
  • 数据集大小不重要恕我直言。如果您执行EXPLAIN SELECT * ...,您将获得一个执行计划。请发布结果,因为这对解决查询性能问题有很大帮助。
  • “解释扩展”在我的帖子中!
  • 对不起,伙计 - 你是 - 似乎将 2 个表中的 like 条件混合在一起会阻止在 container.phone_1 上使用索引。黑暗中的真实镜头-您是否尝试过更改括号括起来的条件?他们目前都在一起 - 尝试将客户的括号放在一起WHERE container.phone_1 LIKE '264%' OR (client.phone_2 LIKE '264%' OR client_phone_3 LIKE '264%')

标签: mysql full-table-scan


【解决方案1】:

使用 and 代替 where。

SELECT * FROM contract JOIN client ON contract.client_id = client.id 加入容器 ON contract.contract_nr = container.contract_nr AND (container.phone_1 LIKE '264%' client.phone_2 LIKE '264%' OR client_phone_3 LIKE '264%')

【讨论】:

  • 这不是有效的 SQL - 你必须有一个 WHERE 子句来应用条件,除非你正在聚合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-10
  • 1970-01-01
  • 2016-11-24
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多