2

在这里,我想在 tracking_no 上加入以下表格,如下所示

SELECT *
FROM tracker_mngr AS pkgdsp 
LEFT JOIN tracker AS taq ON taq.tracking_no LIKE CONCAT('%', pkgdsp.tracking_no ,'%')

但是执行查询需要更多时间,以下是表结构

表结构:

CREATE TABLE `tracker_mngr` (
`id_package_dispatching` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`tracking_no` VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (`id_package_dispatching`),
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `tracker` (
`tracking_no` VARCHAR(50) NOT NULL DEFAULT '',
`status` VARCHAR(100) NOT NULL DEFAULT '',
`status_input_date` VARCHAR(15) NOT NULL DEFAULT '',
`status_input_time` VARCHAR(4) NOT NULL DEFAULT '',
PRIMARY KEY (`tracking_no`,`status`,`status_input_date`,`status_input_time`),
UNIQUE KEY `idx_tracking_no_status_01` (`tracking_no`,`status`,`status_input_date`,`status_input_time`),
KEY `idx_tracking_no_01` (`tracking_no`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;

但我没有权限在 tracker_mngr 表上创建索引,以下是表 tracker_mngr 中的 tracking_no 示例包含 tracking_no 为

tracking_no A113035604231A A113035604220A-1 113036092514 113036092433-1

和跟踪器包含 tracking_no 作为

tracking_no 113035604231 (A113035604231A) 113035604220 (A113035604220A-1) 113036092514 (113036092514) 113036092433 (113036092433-1)

这是我的查询的解释命令表

+----+-------------+--------+------+---------------+------+---------+------+--------+-------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows   | Extra |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------+
|  1 | SIMPLE      | pkgdsp | ALL  | NULL          | NULL | NULL    | NULL | 127362 |       |
|  1 | SIMPLE      | taq    | ALL  | NULL          | NULL | NULL    | NULL |  79766 |       |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------+

但它需要更多的时间来执行,我已经在上面创建了索引,但它没有使用任何索引进行搜索,如上表所示。那么我怎样才能提高这个查询的性能呢?

4

2 回答 2

3

您的使用column LIKE %column%肯定会击败索引的使用。这基本上相当于对列的内容进行全文搜索。

如果您可以消除%连接逻辑中的第一个登录,您将有机会快速运行此连接。否则你所见即所得。

编辑 LIKE本身并不慢。例如column LIKE 'text%',如果column被索引,则可以正常工作。这column LIKE '%text%'是必然且永远缓慢的。

另一种编辑 JOIN ... ON操作在采用以下形式时要快得多

  ON a.col = b.col

a.col 和 b.col 都有索引。加入这样的操作

 ON a.col = somefunction(b.col)

导致 DBMS 必须运行该函数的次数非常多。你的OR条款使情况变得更糟。

Oracle 和 PostGreSQL 数据库提供功能索引。也就是说,您可以根据需要创建索引somefunction(b.col)。这将有助于您的加入。但是,MySQL 不提供该索引类型。

为了获得良好的性能,您将需要重构数据以使用

 ON taq.tracking_no = pkgdsp.clean_tracking_no

这意味着您将不得不向 pkgdsp 添加一列,并弄清楚如何使用纯化的跟踪号填充它。然后,您将在其上创建一个索引。

这是您在 MySQL 中的唯一选择。它也是迄今为止数据完整性的最佳选择。

*另一个编辑。*

如果您在该表中没有任何以多个字母开头的跟踪号,则此查询将生成您的第一个跟踪号已清理的表。

  SELECT id_package_dispatching,
         CAST(CAST(CASE WHEN ASCII(UPPER(tracking_no))>57 
                   THEN SUBSTR(tracking_no,2) 
                   ELSE tracking_no 
                    END AS INT) AS CHAR) AS tracking_no
    FROM tracker_mngr

这是有效的,因为CAST(... AS INT)忽略了尾随的非整数字符。然后我们将其转换回 CHAR,因为我们希望它与您的其他表中的 tracking_no 具有可比性。

您可以在 LEFT JOIN 操作中使用此清理后的虚拟表来代替原始tracker_mngr表。您仍然需要扫描整个tracker_mngr表,但 ON 操作应该便宜得多。

像这样:

SELECT *
  FROM (
        SELECT id_package_dispatching,
               CAST(CAST(CASE WHEN ASCII(UPPER(tracking_no))>57 
                         THEN SUBSTR(tracking_no,2) 
                         ELSE tracking_no 
                          END AS INT) AS CHAR) AS tracking_no
          FROM tracker_mngr
       )AS pkgv
  LEFT JOIN tracker AS taq ON taq.tracking_no = pkgv.tracking_no

对于将清理后的数据存储在表中,这绝对是一个较差的解决方案,但它应该会有所帮助。

于 2013-04-29T11:37:58.690 回答
0

我正在努力了解您的数据如何匹配。上面评论中的 SQL 与原始帖子中的 SQL 并不完全一致。

但是,假设正如您的 SQL 所建议的那样,跟踪器在 tracking_no 字段中包含一个跟踪号,并且您想从 tracker_mngr 中带回任何记录,其中存储在 tracking_no 中的多个跟踪号之一匹配,然后尝试这样的事情(不是测试): -

SELECT * 
FROM tracker_mngr AS pkgdsp 
LEFT JOIN tracker AS taq 
ON FIND_IN_SET(taq.tracking_no, REPLACE(REPLACE(pkgdsp.tracking_no, ' for (', ',')), ') ', ',') > 0

但是,这有时会带回 2 行(因为 113036092514 出现两次,一次在括号内,一次在括号外)。

还有其他选择,但在进行更多游戏之前,我想看看数据是如何匹配的。

于 2013-04-29T13:24:22.210 回答