关于select ...中的sql性能

时间:2019-06-10 08:51:56

标签: mysql sql

MySQL 5.7.21

我使用池连接数据库并运行SQL

let mysql = require('mysql');
let pool = mysql.createPool(db);
pool.getConnection((err, conn) => {
      if(err){
        ...
      }else{
        console.log('allConnections:' + pool._allConnections.length);
        let q = conn.query(sql, val, (err, rows,fields) => {
        ...

我有一张约有1,000,000条记录的表。我写了一封精选书来记录。

select * from tableA where trackingNo in (?)

我将通过数组参数发送trackingNo。 trackingNo的数量大约为20000。这意味着数组的长度大约为20000。

然后我将索引设置为trackingNo列。 (trackingNo列是varchar类型,不是唯一的,可以为null,空白和所有可能的值)

问题是,我发现这大约需要5分钟才能得到结果! 5分钟是指纯后端sql处理时间。我认为在1,000,000条记录中匹配20000条记录太慢了。您对“ ..”中的选择有什么建议吗?

解释SQL:

id  select_type table   partitions  type    possible_keys          key    key_len   ref   rows   filtered   Extra
1   SIMPLE      tableA  null        ALL     table_tracking_no_idx  null   null      null  999507    50      Using where

2 个答案:

答案 0 :(得分:2)

您可以考虑使用要匹配的跟踪号填充表格。然后,您可以使用内部联接代替当前的WHERE IN方法:

SELECT *
FROM tableA a
INNER JOIN tbl b
    ON a.trackingNo = b.trackingNo;

这具有一个优势,您可以在tbl列上索引新的trackingNo表,以使联接查找变得非常快。

这假设tbl会有一列trackingNo,其中包含您需要考虑的20K +值。

答案 1 :(得分:0)

MySQL为由常量组成的IN列表创建一个二进制搜索树。如documentation中所述:

  

如果所有值都是常量,则根据expr的类型对它们进行评估并排序。然后使用二进制搜索完成对项目的搜索。这意味着,如果IN值列表完全由常量组成,则IN很快。

通常,用常量创建一个单独的表不会大大提高性能。

我认为类型兼容性(例如归类)可能存在一些细微问题,会干扰此过程。

这种类型的查询可能需要全表扫描。如果行很宽,则扫描和返回数据的组合可能会影响性能。我确实同意五分钟是很长的时间,但这可能完全是由于应用程序/ GUI和数据库之间的网络连接。