Я выполняю следующий запрос к представлению с именем shipments_last_twenty_days
:
Q1 :
SELECT shipments_last_twenty_days.* FROM shipments_last_twenty_days
LEFT JOIN customers ON shipments_last_twenty_days.customer_id = customers.id
WHERE customers.store_id = 147;
Товарищ заметил, что запрос потратит почти все время его обработки, выполняющее «Отправку данных», а также то, что на этот раз сильно колебалось, и он предложил, чтобы я разделил запрос на две части: первая для получения только идентификаторов, а вторая для получения всех полей с использованием идентификаторы (если на первом шаге не возвращаются идентификаторы, что происходит примерно в 80% случаев). Он сказал, что это может работать быстрее , и, основываясь на некоторых сегодняшних тестах, я думаю, что он был прав примерно в два раза. Проблема в том, Я не понимаю, почему . Вот два запроса, на которые я разделил исходный запрос:
Q1a (и EXPLAIN
вывод):
SELECT shipments_last_twenty_days.id FROM shipments_last_twenty_days
LEFT JOIN customers ON shipments_last_twenty_days.customer_id = customers.id
WHERE customers.store_id = 147;
+----+-------------+-----------+--------+---------------+---------+---------+-----------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+--------+---------------+---------+---------+-----------------------+-------+-------------+
| 1 | SIMPLE | shipments | range | date | date | 9 | | 61758 | Using where |
| 1 | SIMPLE | customers | eq_ref | PRIMARY | PRIMARY | 4 | customers.customer_id | 1 | Using where |
+----+-------------+-----------+--------+---------------+---------+---------+-----------------------+-------+-------------+
Q1b ( и EXPLAIN
output):
SELECT * FROM shipments_last_twenty_days WHERE id IN (2668955, 2671554);
+----+-------------+-----------+-------+---------------+---------+---------+-----+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+-----+------+-------------+
| 1 | SIMPLE | shipments | range | PRIMARY | PRIMARY | 4 | | 2 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+-----+------+-------------+
... (где 2668955 и 2671554, очевидно, являются значениями, возвращаемыми Q1a ).
Кто-нибудь может мне объяснить почему это? Если разница основана на 80% случаев, когда Q1b не выполняется, потому что Q1a не возвращает результатов ... не должно Q1a (SELECT id
) будет столь же дорогостоящим, как Q1 (SELECT *
), если нечего возвращать?
PS: Я не добавил информацию об индексе или информацию о таблице, потому что я полагаю, что этот результат должен быть независимо от этого, но при необходимости спрашивайте. Кроме того, версия MySQL - 5.1 (я знаю, что она старая).
EDIT (дополнительная информация):
SHOW CREATE VIEW shipments_last_twenty_days;
CREATE ALGORITHM=UNDEFINED DEFINER=`fakeuser`@`0.0.0.0`
SQL SECURITY DEFINER VIEW `shipments_last_twenty_days` AS
select `shipments`.`id` AS `id`,
`shipments`.`prog` AS `prog`,
`shipments`.`customer_id` AS `customer_id`,
`shipments`.`id_corriere` AS `id_corriere`,
`shipments`.`id_destinatario` AS `id_destinatario`,
`shipments`.`id_servizio` AS `id_servizio`,
`shipments`.`id_servizioLDV` AS `id_servizioLDV`,
`shipments`.`id_fattura` AS `id_fattura`,
`shipments`.`id_abbonamento` AS `id_abbonamento`,
`shipments`.`date` AS `date`,
`shipments`.`dataMod` AS `dataMod`,
`shipments`.`dataDel` AS `dataDel`,
`shipments`.`dataCreazioneAWB` AS `dataCreazioneAWB`,
`shipments`.`dataTrackPartenza` AS `dataTrackPartenza`,
`shipments`.`dataTrackConsegna` AS `dataTrackConsegna`,
`shipments`.`hasLDV` AS `hasLDV`,
`shipments`.`nColli` AS `nColli`,
`shipments`.`Contenuto` AS `Contenuto`,
`shipments`.`peso` AS `peso`,
`shipments`.`pesoLDV` AS `pesoLDV`,
`shipments`.`isDocumento` AS `isDocumento`,
`shipments`.`isTrasportoPreziosi` AS `isTrasportoPreziosi`,
`shipments`.`isMerceDaImballare` AS `isMerceDaImballare`,
`shipments`.`isReturn` AS `isReturn`,
`shipments`.`prezzoCalcolato` AS `prezzoCalcolato`,
`shipments`.`prezzoFinale` AS `prezzoFinale`,
`shipments`.`notes` AS `notes`,
`shipments`.`isFatto` AS `isFatto`,
`shipments`.`fatturaImporto` AS `fatturaImporto`,
`shipments`.`fatturaAssicurazione` AS `fatturaAssicurazione`,
`shipments`.`fatturaContrassegno` AS `fatturaContrassegno`,
`shipments`.`isFatturato` AS `isFatturato`,
`shipments`.`isAnnullato` AS `isAnnullato`,
`shipments`.`isModificatoAmministratore` AS `isModificatoAmministratore`,
`shipments`.`valoreContrassegno` AS `valoreContrassegno`,
`shipments`.`valoreAssicurazione` AS `valoreAssicurazione`,
`shipments`.`valoreMerce` AS `valoreMerce`,
`shipments`.`shipmentValueCurrency` AS `shipmentValueCurrency`,
`shipments`.`isConsegnatoTracking` AS `isConsegnatoTracking`,
`shipments`.`failedDelivery` AS `failedDelivery`,
`shipments`.`bookingNumber` AS `bookingNumber`,
`shipments`.`riferimentoMittente` AS `riferimentoMittente`,
`shipments`.`masterTrk` AS `masterTrk`,
`shipments`.`isPagamentoDaziAlMittente` AS `isPagamentoDaziAlMittente`,
`shipments`.`isEsportato` AS `isEsportato`,
`shipments`.`labelMasterExtension` AS `labelMasterExtension`,
`shipments`.`contrassegnoTipo` AS `contrassegnoTipo`,
`shipments`.`isNotificaInternaInviata` AS `isNotificaInternaInviata`,
`shipments`.`trackDataPartenza` AS `trackDataPartenza`,
`shipments`.`trackDataConsegna` AS `trackDataConsegna`,
`shipments`.`trackFirmaConsegna` AS `trackFirmaConsegna`,
`shipments`.`trackDataSalvataggio` AS `trackDataSalvataggio`,
`shipments`.`isCreatoDaWebService` AS `isCreatoDaWebService`,
`shipments`.`shipmentOrigin` AS `shipmentOrigin`,
`shipments`.`boxdropId` AS `boxdropId`,
`shipments`.`isControllataFatturaFornitore` AS `isControllataFatturaFornitore`,
`shipments`.`noteConsegna` AS `noteConsegna`,
`shipments`.`webServiceTipo` AS `webServiceTipo`,
`shipments`.`isTrackDatiConsegnaManuali` AS `isTrackDatiConsegnaManuali`,
`shipments`.`numeroChiusura` AS `numeroChiusura`,
`shipments`.`dataChiusura` AS `dataChiusura`,
`shipments`.`corriere` AS `corriere`,
`shipments`.`isChiusoManifestSDA` AS `isChiusoManifestSDA`,
`shipments`.`costoAcquisto` AS `costoAcquisto`,
`shipments`.`isConsegnaSabato` AS `isConsegnaSabato`,
`shipments`.`isPortoAssegnato` AS `isPortoAssegnato`,
`shipments`.`portoAssegnato_codice` AS `portoAssegnato_codice`,
`shipments`.`portoAssegnato_codice_cap` AS `portoAssegnato_codice_cap`,
`shipments`.`pagamentoDazi_codice` AS `pagamentoDazi_codice`,
`shipments`.`pagamentoDazi_cap` AS `pagamentoDazi_cap`,
`shipments`.`isChiusoBorderoSGT` AS `isChiusoBorderoSGT`,
`shipments`.`isRichiestaImport` AS `isRichiestaImport`,
`shipments`.`idDepartment` AS `idDepartment`,
`shipments`.`use_dpd_predict` AS `use_dpd_predict`,
`shipments`.`dpd_predict_channel` AS `dpd_predict_channel`,
`shipments`.`dpd_predict_value` AS `dpd_predict_value`,
`shipments`.`dpd_predict_language` AS `dpd_predict_language`,
`shipments`.`UPSSignatureRequired` AS `UPSSignatureRequired`,
`shipments`.`returnRecipientOption` AS `returnRecipientOption`,
`shipments`.`returnRecipientDepartmentId` AS `returnRecipientDepartmentId`,
`shipments`.`returnOptionUPS` AS `returnOptionUPS`,
`shipments`.`exportedToManifest` AS `exportedToManifest`,
`shipments`.`shipmentSource` AS `shipmentSource`,
`shipments`.`valueMBESafeValue` AS `valueMBESafeValue`,
`shipments`.`goodsDescriptionMBESafeValue` AS `goodsDescriptionMBESafeValue`,
`shipments`.`NEXShippingCollectionId` AS `NEXShippingCollectionId`,
`shipments`.`NEXShippingId` AS `NEXShippingId`,
`shipments`.`serviceAfterDowngrade` AS `serviceAfterDowngrade`,
`shipments`.`UPSAdultSignatureRequired` AS `UPSAdultSignatureRequired`,
`shipments`.`addressUPSAccessPoint` AS `addressUPSAccessPoint`
from `shipments`
where ((`shipments`.`date` >= '2020-04-18 00:00:00') and
(`shipments`.`date` < '2020-05-09 00:00:00') and
(`shipments`.`isAnnullato` = 0) and
(`shipments`.`hasLDV` is true) and
(`shipments`.`isEsportato` is false))
SHOW INDEX FROM shipments
+-----------+------------+----------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------+------------+----------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| shipments | 0 | PRIMARY | 1 | id | A | 2636401 | | | | BTREE | |
| shipments | 1 | MittentiOrdini | 1 | id_destinatario | A | 2636401 | | | YES | BTREE | |
| shipments | 1 | masterTrk | 1 | masterTrk | A | 2636401 | | | YES | BTREE | |
| shipments | 1 | prog | 1 | prog | A | 376628 | | | YES | BTREE | |
| shipments | 1 | customer_id_and_date | 1 | customer_id | A | 32548 | | | YES | BTREE | |
| shipments | 1 | customer_id_and_date | 2 | date | A | 2636401 | | | YES | BTREE | |
| shipments | 1 | date | 1 | date | A | 2636401 | | | YES | BTREE | |
+-----------+------------+----------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
PS: Мне известно, что MySQL, похоже, не использует составной индекс, который я создал для этого запроса. Я попробую запустить его без представления, а затем думаю, что MySQL будет его использовать (представление было улучшением производительности, когда у меня не было этого индекса). В любом случае, для целей этой публикации меня больше всего интересует, почему Q1a + Q1b может быть быстрее, чем Q1 , я хочу понять это (если это не имеет смысла с теоретической точки зрения, скажите, пожалуйста, возможно, мои тесты были неправильными).