【问题标题】:MariaDB performance issue with "Where IN" clause“Where IN”子句的 MariaDB 性能问题
【发布时间】:2015-12-18 10:50:31
【问题描述】:

我的 SQL 代码有问题。我们开发了一个在 MySQL 上运行的应用程序,它运行良好。所以我决定尝试一下 MariaDB,并将它安装在开发机器上。在某个查询 Stmt 上,我有一个我不明白的性能问题。查询如下:

 SELECT SAMPLES.*, UNIX_TIMESTAMP(SAMPLES.SAMPLE_DATE) as TIMESTAMP,RAWS.VALUE, DATAKEYS.RAW_ID, DATAKEYS.DATA_KEY_VALUE, DATAKEYS.DATA_KEY_ID, KEYDEF.KEY_NAME, KEYDEF.LDD_ID 
FROM 
PDS.TABLE_SAMPLES SAMPLES 
RIGHT OUTER JOIN PDS.TABLE_RAW_VALUES RAWS ON SAMPLES.SAMPLE_ID = RAWS.SAMPLE_ID 
RIGHT OUTER JOIN PDS.TABLE_SAMPLE_DATA_KEYS DATAKEYS ON(DATAKEYS.RAW_ID = RAWS.RAW_ID AND DATAKEYS.SAMPLE_ID = SAMPLES.SAMPLE_ID) OR 
(DATAKEYS.RAW_ID = 0 AND DATAKEYS.SAMPLE_ID = SAMPLES.SAMPLE_ID) 
RIGHT OUTER JOIN PDS.TABLE_DATA_KEY_DEFINITION KEYDEF ON(DATAKEYS.DATA_KEY_ID = KEYDEF.DATA_KEY_ID) 
WHERE 
SAMPLES.SAMPLE_ID IN(1991331,1991637,1991941,2046105,2046411,2046717,2047023,2047635,2047941,2048247)
AND (SAMPLES.PARAMETER_ID = 9) 
GROUP BY DATAKEYS.DATA_KEY_ID, RAWS.RAW_ID, DATAKEYS.DATA_KEY_ID 
ORDER BY SAMPLES.SAMPLE_ID, DATAKEYS.RAW_ID;

只要我在“WHERE IN”条件中只得到一个值,查询就需要大约 10 毫秒来执行。这与 MySQL 5.6 所采用的大致相同。 一旦我在那里添加另一个值,查询时间就会增加到几分钟。在 MySQL 中,它的提升非常缓慢,在 MySQL 上显示的查询大约需要 150 毫秒,在使用完全相同的数据集的新 MariaDB 安装上大约需要 140 秒。

我不是 SQL 专家,你能给我一些线索如何优化查询以按预期运行吗?

【问题讨论】:

  • samples.sample_id 是索引列吗?
  • 只是备注,right outer join在这里没有意义如果你在where子句中使用sample_id,最好全部改成inner join
  • 在您的选择语句中添加SAMPLES.* 有什么意义,您没有对其中任何一个进行分组
  • 是的,sample_id 被索引并且是唯一的
  • 你能发一个explain吗?可以帮助理解。

标签: mysql sql mariadb


【解决方案1】:

right outer joins 正在通过where 子句转换为内部联接。因此,只需使用正确的join 类型(我不确定这是否会影响查询的优化,但它会):

SELECT SAMPLES.*, UNIX_TIMESTAMP(SAMPLES.SAMPLE_DATE) as TIMESTAMP,RAWS.VALUE, DATAKEYS.RAW_ID, DATAKEYS.DATA_KEY_VALUE, DATAKEYS.DATA_KEY_ID, KEYDEF.KEY_NAME, KEYDEF.LDD_ID 
FROM PDS.TABLE_SAMPLES SAMPLES JOIN
     PDS.TABLE_RAW_VALUES RAWS
     ON SAMPLES.SAMPLE_ID = RAWS.SAMPLE_ID JOIN
     PDS.TABLE_SAMPLE_DATA_KEYS DATAKEYS
     ON (DATAKEYS.RAW_ID = RAWS.RAW_ID AND DATAKEYS.SAMPLE_ID = SAMPLES.SAMPLE_ID) OR 
        (DATAKEYS.RAW_ID = 0 AND DATAKEYS.SAMPLE_ID = SAMPLES.SAMPLE_ID) JOIN
     PDS.TABLE_DATA_KEY_DEFINITION KEYDEF
     ON DATAKEYS.DATA_KEY_ID = KEYDEF.DATA_KEY_ID)
WHERE SAMPLES.SAMPLE_ID IN (1991331, 1991637, 1991941, 2046105, 2046411, 2046717, 2047023, 2047635, 2047941, 2048247) AND
      (SAMPLES.PARAMETER_ID = 9) 
GROUP BY DATAKEYS.DATA_KEY_ID, RAWS.RAW_ID, DATAKEYS.DATA_KEY_ID 
ORDER BY SAMPLES.SAMPLE_ID, DATAKEYS.RAW_ID;

接下来,这个查询的最佳索引——不管IN 中有多少值,是复合索引PDS.TABLE_SAMPLES(PARAMETER_ID, SAMPLE_ID)。这会处理WHERE 子句。

由于您的查询在某些情况下运行得很快,我假设其他表具有适合连接的索引。

【讨论】:

  • 正确的索引,PDS.TABLE_SAMPLES(PARAMETER_ID, SAMPLE_ID) 是该表的主键。但是,错误的连接类型是问题所在。使用内部连接时,问题消失了。谢谢!
【解决方案2】:

尝试使用“exists”而不是运算符“IN”并使用子查询 而不是使用 sample_id。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多