【问题标题】:Mariadb - interpretation of where clause depedns on conditions orderMariadb - where 子句的解释取决于条件顺序
【发布时间】:2017-02-08 16:29:00
【问题描述】:

我们刚刚从 MySQL 5.5.20 迁移到 MariaDB 5.5.50 我在一个查询中发现了一个非常奇怪的问题。

此查询适用于 Mysql,但不适用于 MariaDB:

SELECT 'za_faktura' AS tabulka,
       za_faktura.id,
       za_faktura.r_cislo,
       za_faktura.o_za_platba,
       za_faktura.a_vystaveni,
       za_faktura.a_splatnost,
       za_faktura.a_zaplaceno,
       0            AS storno,
       za_faktura.p_fakturovano,
       za_faktura.p_fakturovano_mena,
       za_faktura.p_fakturovano_dph,
       za_faktura.p_fakturovano_dph_mena,
       za_faktura.p_zaplaceno,
       za_faktura.p_zaplaceno_mena,
       za_faktura.p_zaplaceno_dph,
       za_faktura.p_zaplaceno_dph_mena
FROM   za_faktura
       INNER JOIN zamn_zakazky_faktury
               ON zamn_zakazky_faktury.i_za_faktura = za_faktura.id
WHERE  zamn_zakazky_faktury.i_za_zakazka = '27580'
       AND za_faktura.i_od = '6660'
       AND za_faktura.i_pro = '3916'
       AND za_faktura.p_fakturovano >= '600.00'
       AND za_faktura.p_fakturovano_mena = 'CZK'
       AND ( ( za_faktura.id = '26282'
               AND za_faktura.p_fakturovano_mena = 'CZK'
               AND za_faktura.p_fakturovano > '600' )
              OR ( za_faktura.id = '26243'
                   AND za_faktura.p_fakturovano_mena = 'CZK'
                   AND za_faktura.p_fakturovano > '3000' )
              OR ( za_faktura.id <> '26282'
                   AND za_faktura.id <> '26243' ) )
ORDER  BY za_faktura.p_fakturovano - '600.00' ASC 

从玛丽亚那里得到解释:

id select_type table type possible_keys key key_len ref rows filtered Extra  
1 SIMPLE zamn_zakazky_faktury range  PRIMARY            PRIMARY 4                         NULL 4 75.00 Using where; Using index; Using temporary; Using f...  
1 SIMPLE za_faktura           eq_ref PRIMARY,i_od,i_pro PRIMARY 4 guidepraguecz.zamn_zakazky_faktury.i_za_faktura 1 100.00 Using index condition; Using where

如果我在最后一个子句中替换了 OR 的顺序,它适用于 MariaDB:

id select_type table type possible_keys key key_len ref rows filtered Extra  
1 SIMPLE zamn_zakazky_faktury ref PRIMARY                    PRIMARY 4 const                4 100.00 Using where; Using index; Using temporary; Using filesort  
1 SIMPLE za_faktura               eq_ref  PRIMARY,i_od,i_pro PRIMARY 4 guidepraguecz.zamn_zakazky_faktury.i_za_faktura 1 100.00 Using index condition; Using where

那么……

SELECT 'za_faktura' AS tabulka,
       za_faktura.id,
       za_faktura.r_cislo,
       za_faktura.o_za_platba,
       za_faktura.a_vystaveni,
       za_faktura.a_splatnost,
       za_faktura.a_zaplaceno,
       0            AS storno,
       za_faktura.p_fakturovano,
       za_faktura.p_fakturovano_mena,
       za_faktura.p_fakturovano_dph,
       za_faktura.p_fakturovano_dph_mena,
       za_faktura.p_zaplaceno,
       za_faktura.p_zaplaceno_mena,
       za_faktura.p_zaplaceno_dph,
       za_faktura.p_zaplaceno_dph_mena
FROM   za_faktura
       INNER JOIN zamn_zakazky_faktury
               ON zamn_zakazky_faktury.i_za_faktura = za_faktura.id
WHERE  zamn_zakazky_faktury.i_za_zakazka = '27580'
       AND za_faktura.i_od = '6660'
       AND za_faktura.i_pro = '3916'
       AND za_faktura.p_fakturovano >= '600.00'
       AND za_faktura.p_fakturovano_mena = 'CZK'
       AND ( ( za_faktura.id <> '26282'
               AND za_faktura.id <> '26243' )
              OR ( za_faktura.id = '26282'
                   AND za_faktura.p_fakturovano_mena = 'CZK'
                   AND za_faktura.p_fakturovano > '600' )
              OR ( za_faktura.id = '26243'
                   AND za_faktura.p_fakturovano_mena = 'CZK'
                   AND za_faktura.p_fakturovano > '3000' ) )
ORDER  BY za_faktura.p_fakturovano - '600.00' ASC 

有没有人发现任何类似的奇怪问题?是否有任何配置等解决方案...我在网上找不到任何解决方案。如果它是 MariaDB 中的一个错误,它应该会带来很多从 MySQL 切换的复杂性。

谢谢,

【问题讨论】:

  • 很明显,这两个查询除了两个或条件的排序之外并不完全相同。
  • 我无法复制这个 - 你确定数据库是一样的吗?

标签: mysql sql-server mariadb mariasql


【解决方案1】:

我不知道“奇怪的问题”,但这个复合索引可能会加快它们的速度,这样问题就无关紧要了:

za_faktura: INDEX(i_od, i_pro, p_fakturovano_mena, p_fakturovano)

前 3 列可以是任意顺序;最后一个必须是最后一个(由于是“范围”)。 More discussion.

通常最好避免ORDER BY中的表达式:

ORDER  BY za_faktura.p_fakturovano - '600.00' ASC  -- change to:
ORDER  BY za_faktura.p_fakturovano ASC

那些会给你相同的顺序。前者不能使用索引。 (我不能确定我给你的索引是否会导致它使用索引。)

您只重新排列了OR,对吗?由于OR通常无法优化,如果有差异我会感到惊讶。

让我们看看两台机器上的索引。

【讨论】:

  • 谢谢,索引加快了查询速度,但我的问题是第一个查询只在 MySQL 上返回一行。 Maria 的结果为空。具有重新排列 OR 的第二个返回两个上的一行。 za_faktura 表有大约 65000 行。
  • 请验证数据集和查询是否相同,然后向 mariadb.com 提交错误。
猜你喜欢
  • 2018-08-06
  • 2018-08-07
  • 2021-03-10
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多