社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

为什么mysql连接查询-完全扫描不使用索引

jaechoi • 4 年前 • 922 次点击  

当我只在一个表中选择查询时,我们得到了使用索引的响应,但是当在查询中使用join statemnt时,mysql会对表进行完全扫描吗?

第一查询

select *
    from t_deposit_trx
    where remit_tx_id = '3a33ff14-8d31-45d0-b64f-8a251c4b19a5'

1个简单的T_存款参考T_存款T_汇款ID_指数
使用索引条件的t_deposit_trx_remit_tx_id_index 110 const 1

第二查询

select tx_id
from t_settle_trx
where report_date >= '2019-03-01'
  and report_date <= '2019-03-16'
  and tx_type = 'CANCEL'

1个简单的t_结算t_trx range t_结算t_trx_report_date_tx_type_index t_结算t_trx_report_date_tx_type_index 196 5263使用索引条件

2查询操作良好。 使用指数和速度都很好。

但是加入两张桌子,很慢。

select * from t_deposit_trx
force index (t_deposit_trx_remit_tx_id_index)
where remit_tx_id in (
  select tx_id
  from t_settle_trx
  where report_date >= '2019-03-01'
    and report_date <= '2019-03-02'
    and tx_type = 'CANCEL'
)

一级T_矿床,全部55724
1个主t_结算t_trx range t_结算t_trx_report_date_tx_type_index t_结算t_trx_report_date_tx_type_index 196 299,使用索引条件;使用where;firstmatch(t_deposit_trx);使用连接缓冲区(flat,bnl join)

我们可以看到上面的结果。 t_settle_trx use range scan and get tx_id and next我希望查询使用索引 “t_settle_trx_report_date_tx_type_索引” 但它使用全扫描…

我不知道为什么?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40198
 
922 次点击  
文章 [ 3 ]  |  最新文章 4 年前
jaechoi
Reply   •   1 楼
jaechoi    5 年前

伙计们。。 谢谢你对我的问题感兴趣。

以上两个表在暂存环境和生产环境中具有相同的索引结构。 使用伽辽星团。

我真正想知道的是,他们为什么使用不同的“执行计划”? 特别是在生产环境中,连接查询非常慢。

我昨天做的是…

select * from t_deposit_trx
where remit_tx_id in (
  select tx_id
  from t_settle_trx
  where report_date >= '2019-03-01'
    and report_date <= '2019-03-02'
    and tx_type = 'CANCEL'
)

我将此查询稍微更改为

select * from t_deposit_trx
where tx_seq in (
  select tx_seq 
  from t_settle_trx
  where report_date >= '2019-03-01'
    and report_date <= '2019-03-02'
    and tx_type = 'CANCEL'
)

然后先进行“范围扫描”和“索引扫描”。 但两个发送序列值是不同的。它没有任何关系。 这只是测试它们在连接查询时是否可以使用索引。

你知道我的意思吗? 这意味着它们可以在连接时使用索引。

那么是否存在环境变量问题、密钥长度限制或其他问题?

谢谢你读我的文章。

tcadidot0
Reply   •   2 楼
tcadidot0    5 年前

我希望这不会比您的第一个查询慢:

SELECT t1.* FROM t_deposit_trx t1 
INNER JOIN t_settle_trx t2
ON t1.remit_tx_id=t2.tx_id
WHERE t2.report_date >= '2019-03-01'
AND t2.report_date <= '2019-03-02'
AND t2.tx_type='CANCEL';
Rick James
Reply   •   3 楼
Rick James    5 年前

查询2是 最优的。转动索引:

INDEX(tx_type, report_date)

也就是说,用 = 第一 ,与基数无关。

IN ( SELECT ... ) JOIN . (在较新版本中, 可以 转换为 加入 )

试试看:

SELECT  d.*
    FROM  t_settle_trx AS s
    JOIN  t_deposit_trx AS d  ON s.tx_id = d.remit_tx_id
    WHERE  s.tx_type = 'CANCEL'
      AND  s.report_date >= '2019-03-01'
      AND  s.report_date <  '2019-03-01' + INTERVAL 2 DAY

s: INDEX(tx_type, report_date, tx_id)
d: INDEX(remit_tx_id)

想想这个 SELECT 用一个 加入 从一张桌子开始 WHERE 条款.

(注意:我排列了表和where子句的顺序,这样您就可以看到优化器是如何思考的。表的顺序和where子句的顺序不相关;优化器将根据需要重新排列。)

我的公式应该

  • 充分利用两个表上的索引。
  • 避免全表扫描
  • 第一 它查看的表

全表扫描是 必然是件坏事。如果 一张桌子无论如何都会被触摸,实际上 更快 只需扫描表,而不在索引的btree和数据的btree之间跳转。(你的 具体的 凯斯还有其他不足之处,我把重点放在了这些方面。)

INDEX(tx_type, report_date, tx_id)

是“覆盖”的,因为查询所需的所有列都在一个索引中找到。覆盖“给你一个稍微额外的性能提升。它显示在 EXPLAIN 通过 Using index (不是) Using index condition )

对于tx_seq,这可能是最佳的:

INDEX(tx_type, report_date, tx_seq)