Чувствительность к регистру имени поля в подзапросах mysql (версия 5.6 против версии 8) - PullRequest
0 голосов
/ 11 июля 2019

Обновление с MySQL5.6 до MySQL8 создает проблему для чувствительности к регистру имен полей в подзапросах.

Я пытался прочитать документацию по MySQL8 и различные статьи, связанные с чувствительностью к регистру, но не смог найти решение.

SELECT  productId 
  FROM ( SELECT a.PRODUCTID 
           FROM ( SELECT ProdId ProductId 
                    FROM tblproductmaster 
                   ORDER BY CreatedDateTime DESC limit 10 ) a ) a ;

Ожидаемый результат как в версии 5.6, так и в версии 8

+-----------------+
| productId       |
+-----------------+
| PROJTZ00734     |
| 75882M56R00B4   |
| 1161085S10-B200 |
| HRZ00136        |
| HRZ00135        |
| HRZ00134        |
| HRZ00133        |
| IMPOZ00148      |
| IMPOZ00147      |
| MAINZ01682      |
+-----------------+

Но фактический результат в версии 5.6 равен

+-----------------+
| productId       |
+-----------------+
| PROJTZ00734     |
| 75882M56R00B4   |
| 1161085S10-B200 |
| HRZ00136        |
| HRZ00135        |
| HRZ00134        |
| HRZ00133        |
| IMPOZ00148      |
| IMPOZ00147      |
| MAINZ01682      |
+-----------------+

, а в версии 8 -

+---------------+
| PRODUCTID     |
+---------------+
| 46201M79G00B3 |
| 46201M59K00B2 |
| 59288M81R10   |
| 59238M81R00   |
| 59286M81R10   |
| 59236M81R00   |
| 59234M81R00   |
| MAINZ01482    |
| MAINZ01481    |
| CONZ00171     |
+---------------+

1 Ответ

0 голосов
/ 12 июля 2019

Имена столбцов без учета регистра по определению :

Имена столбцов, индексов, хранимых подпрограмм и событий не чувствительны к регистру на любой платформе, а также псевдонимы столбцов.

MySQL может выбрать любую версию, но выберет последнюю версию, с которой он сталкивается. Который не обязательно является версией, которую вы думаете.

Здесь происходит то, что оптимизатор в MySQL 8 оптимизировал запрос путем слияния двух внешних слоев в один , тогда как MySQL 5.6 еще не знал такого рода оптимизации. План выполнения в MySQL 5.6. должен выглядеть как

id  select_type table               type    possible_keys   ...         
1   PRIMARY     <derived2>          ALL                         
2   DERIVED     <derived3>          ALL                         
3   DERIVED     tblproductmaster    ALL

в то время как для MySQL 5.7 и выше вы должны получить строку меньше:

id  select_type table               type    possible_keys   ...         
1   PRIMARY     <derived3>          ALL                         
3   DERIVED     tblproductmaster    ALL

Это, очевидно, хорошая идея, поскольку она потенциально ускоряет выполнение вашего запроса из-за необходимости выполнять меньше работы. По сути, MySQL упростил ваш запрос до чего-то вроде

SELECT a.PRODUCTID from (SELECT ProdId ProductId FROM tblproductmaster 
               ORDER BY CreatedDateTime DESC limit 10 ) a

Нет спецификации, которая требует, чтобы MySQL выбирал внешнее или внутреннее написание в процессе слияния (и это может измениться в будущих версиях). MySQL, однако, будет использовать псевдоним, который вам следует использовать здесь, если вам нужен конкретный случай:

SELECT productId as productId FROM ( SELECT a.PRODUCTID from ( ... ) a ) a 

должно дать

+-----------------+
| productId       |
+-----------------+
| PROJTZ00734     |

К сожалению, вам нужно будет изменить (все) ваши запросы для этого, здесь нет опции «всегда выбирать самый орфографический случай», так как для MySQL регистр не имеет значения и никогда не задавался, а просто Оказалось, что MySQL до сих пор выбирал тот случай, который вы предпочитали.

Однако вы можете полностью отключить эту оптимизацию слияния. Хотя это может сделать некоторые запросы медленнее, оно может работать как временное решение, чтобы заставить ваш код работать до тех пор, пока вы его не попробуете (что вы должны сделать в конце концов). Чтобы отключить derived_merge (и оставить все остальные параметры с их настройками по умолчанию), вы можете использовать переключатель оптимизатора

set global optimizer_switch='derived_merge=off';

Не забудьте добавить его в файл конфигурации, иначе он не выдержит перезапуск сервера. Это должно заставить ваши запросы вести себя как MySQL 5.6 в отношении слияния, и как побочный эффект, вы должны получить правописание MySQL 5.6. Хотя, как оговорка, поведение все еще не определено, поэтому крайние случаи или будущие версии могут вести себя по-другому.

...