简体   繁体   English

MySQL临时文件排序问题

[英]Mysql temporary, filesort issue

From my research, I'm not even sure it is possible to avoid the temporary / filesort with the following query due to the group by and order by. 根据我的研究,由于group by和order by,我什至不能确定是否可以通过以下查询来避免临时/文件排序。 I'm also not one to ask without doing a ton of research on my own. 如果我自己不做大量研究,我也不是一个要问的人。 But if anyone can help figure out how to avoid the filesort or point me in the correct direction - even if its completely re-writing the query or suggesting something code side, it would be much appreciated. 但是,如果有人可以帮助您确定如何避免文件排序或将我指向正确的方向-即使它完全重新编写了查询或建议了某些代码方面,也将不胜感激。 I've completely hit a wall trying to figure this one out. 我完全碰壁了,试图弄清楚这一点。 There's a link to the output of the explain at the bottom. 底部有一个解释输出的链接。

explain select CONCAT(scfs.name, ' ',scfs.state,' ',scfs.zip_code) as scfname, scfs.zip_code, IF(date(s.scan_datetime) <= date(NOW()),date(s.scan_datetime),null) as scandate, count(*) as total,
                    sum(case when s.delivery_status = 1 then 1 else 0 end) as final

                     from order_addresses oa
                         left join pkg_data_unique s
                            on oa.trace_code = s.pkg_trace_code
                         inner join scf_zip_codes z
                            on SUBSTR(oa.zip,1,3) = z.zip_code
                         inner join scfs scfs
                            on z.scf_zip_code = scfs.zip_code



                    where oa.order_id = 160387

                    group by 1,2,3
                    order by scfs.zip_code, scandate

CREATE ORDER ADDRESSES 创建订单地址

CREATE TABLE order_addresses ( id int(10) unsigned NOT NULL AUTO_INCREMENT, order_id int(11) NOT NULL, name varchar(100) COLLATE utf8_unicode_ci NOT NULL, address varchar(100) COLLATE utf8_unicode_ci NOT NULL, address2 varchar(100) COLLATE utf8_unicode_ci NOT NULL, city varchar(50) COLLATE utf8_unicode_ci NOT NULL, state varchar(15) COLLATE utf8_unicode_ci NOT NULL, zip char(5) COLLATE utf8_unicode_ci NOT NULL, zip4 int(11) NOT NULL, imb_digits char(31) COLLATE utf8_unicode_ci NOT NULL, trace_code char(20) COLLATE utf8_unicode_ci NOT NULL, created_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', updated_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', deleted_at timestamp NULL DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY order_address_unique (order_id,imb_digits,name,address,address2,city,state,zip), KEY order_addresses_order_id_index (order_id), KEY order_addresses_name_index (name), KEY order_addresses_address_index (address), KEY order_addresses_city_index (city), KEY order_addresses_state_index (state), KEY order_addresses_zip_index (zip), KEY order_addresses_imb_digits_index (imb_digits), KEY order_addresses_trace_code_index (trace_code), KEY order_id_trace_code (order_id,trace_code) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=487714542 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPACT

PKG DATA UNIQUE TABLE PKG数据唯一表

CREATE TABLE pkg_data_unique ( id int(10) unsigned NOT NULL AUTO_INCREMENT, zip char(5) COLLATE utf8_unicode_ci NOT NULL, opcode int(11) NOT NULL, pkg_trace_code char(20) COLLATE utf8_unicode_ci NOT NULL, scan_datetime datetime NOT NULL, original_scan_datetime datetime NOT NULL, delivery_status int(11) NOT NULL, created_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', updated_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (id), UNIQUE KEY pkg_data_unique_pkg_trace_code_index (pkg_trace_code) USING BTREE, KEY pkg_data_unique_zip_index (zip), KEY pkg_data_unique_opcode_index (opcode), KEY pkg_data_unique_scan_datetime_index (scan_datetime), KEY pkg_data_unique_delivery_status_index (delivery_status), KEY pkg_data_unique_original_scan_datetime (original_scan_datetime) ) ENGINE=InnoDB AUTO_INCREMENT=490667214 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPACT

SCF ZIP CODES SCF邮编

CREATE TABLE scf_zip_codes ( id int(10) unsigned NOT NULL AUTO_INCREMENT, scf_zip_code varchar(3) COLLATE utf8_unicode_ci NOT NULL, zip_code varchar(3) COLLATE utf8_unicode_ci NOT NULL, created_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', updated_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (id), KEY scf_zip_codes_scf_zip_code_index (scf_zip_code), KEY scf_zip_codes_zip_code_index (zip_code) ) ENGINE=InnoDB AUTO_INCREMENT=916 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPACT

SCFS 可持续发展中心

CREATE TABLE scfs ( id int(10) unsigned NOT NULL AUTO_INCREMENT, label_id bigint(20) unsigned NOT NULL, zip_code varchar(5) COLLATE utf8_unicode_ci NOT NULL, name varchar(255) COLLATE utf8_unicode_ci NOT NULL, state varchar(255) COLLATE utf8_unicode_ci NOT NULL, locale_key varchar(255) COLLATE utf8_unicode_ci NOT NULL, created_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', updated_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (id), UNIQUE KEY scfs_label_id_unique (label_id), UNIQUE KEY scfs_zip_code_unique (zip_code), KEY scfs_name_index (name), KEY scfs_state_index (state) ) ENGINE=InnoDB AUTO_INCREMENT=196 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPACT

Image of Explain Output 解释输出图像

figure out how to avoid the filesort or point me in the correct direction 弄清楚如何避免文件排序或将我指向正确的方向

The alternative(s) involve changing the intent of your query. 备选方案包括更改查询的意图。

    group by  1,2,3
    order by  scfs.zip_code, scandate

The GROUP BY may involve a filesort an temp table. GROUP BY可能涉及对临时表进行文件排序。

The ORDER BY will certainly involve (another) filesort and temp table because it does not match the GROUP BY . ORDER BY当然会涉及(另一个)文件排序和临时表,因为它与GROUP BY不匹配。 No, shuffling to GROUP BY 2,1,3 (since col 2 is the zip code) won't help. 不,改组为GROUP BY 2,1,3 (因为col 2是邮政编码)将无济于事。

If you can live with this, GROUP BY 2,1,3 ORDER BY 2,1,3 , then you can get rid of one filesort and have approximately the same output. 如果您可以使用GROUP BY 2,1,3 ORDER BY 2,1,3 ,那么您可以摆脱一个文件排序并获得大致相同的输出。

Is your query "slow"? 您的查询“慢”吗? 'Filesort' is not the main performance killer. Filesort不是主要的性能杀手。

There are a few things that can speed up the query some: 有一些事情可以加快查询速度:

  • Zipcodes (and some other things) don't need utf8; 邮政编码(以及其他一些东西)不需要utf8; change the column to CHARACTER SET ascii . 将列更改为CHARACTER SET ascii
  • Secondary keys, when used, need to drill down the PRIMARY KEY BTree to find the row. 使用辅助键时,需要向下钻取PRIMARY KEY BTree才能找到该行。 Consider which, if any, secondary indexes could be promoted to PRIMARY KEY . 考虑可以将哪些二级索引提升为PRIMARY KEY
  • date(s.scan_datetime) <= date(NOW()) --> s.scan_datetime <= CURDATE() date(s.scan_datetime) <= date(NOW()) -> s.scan_datetime <= CURDATE()
  • sum(case when s.delivery_status = 1 then 1 else 0 end) => sum(case when s.delivery_status = 1) since a boolean expression evaluates to 1 or 0. sum(case when s.delivery_status = 1 then 1 else 0 end) => sum(case when s.delivery_status = 1)因为布尔表达式的计算结果为1或0。
  • INDEX(a), INDEX(a,b) --> the first can be DROPped without loss of functionality. INDEX(a), INDEX(a,b) ->可以DROPped第一个而不损失功能。
  • scfs has 3 unique keys; scfs具有3个唯一键; id seems useless. id似乎没用。 Promote zipcode to be the PK and make it CHAR(5) CHARACTER SET ascii . zipcode升级为PK,并将其设置为CHAR(5) CHARACTER SET ascii It will be 5 bytes instead of id's 4 bytes. 这将是5个字节,而不是id的4个字节。
  • Don't blindly use (255) ; 不要盲目使用(255) ; pick a smaller (but safe) value. 选择一个较小(但安全)的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM