Индекс не используется в зависимости от привязки параметра и кодировкиPhp

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Индекс не используется в зависимости от привязки параметра и кодировки

Сообщение Anonymous »

Вопрос
Почему мой индекс игнорируется при определенных обстоятельствах, что приводит к замедлению выполнения. Я нашел причину в сочетании использования UNION ALL + выбранного API базы данных PHP + выбранной кодировки + использованной реализации привязки параметров.
Настройка
Я создал представление my_view, которое выглядит следующим образом:
SELECT type FROM table1

UNION ALL

SELECT type FROM table2

И таблица1, и таблица2 имеют одинаковую структуру, которая выглядит следующим образом:
CREATE TABLE table1
(
id INT UNSIGNED AUTO_INCREMENT,
type INT NOT NULL,
... -- some more data columns
PRIMARY KEY (id)
);

CREATE INDEX my_idx ON table1 (type);


Теперь я хочу выбрать все записи, где тип = 1. Это должно быть довольно просто:
SELECT * FROM my_view WHERE type = 1;

Выполнение EXPLAIN для этого запроса дает следующий результат:
┌────┬─────────────┬────────────┬───────┬───────────────┬────────┬─────────┬────────┬──────┬─────────────┐
│ id │ select_type │ table │ type │ possible_keys │ key │ key_len │ ref │ rows │ Extra │
╞════╪═════════════╪════════════╪═══════╪═══════════════╪════════╪═════════╪════════╪══════╪═════════════╡
│ 1 │ PRIMARY │ │ ALL │ │ │ │ │ 110 │ Using where │
│ 2 │ DERIVED │ table1 │ const │ my_idx │ my_idx │ 5 │ const │ 72 │ Using index │
│ 3 │ UNION │ table2 │ const │ my_idx │ my_idx │ 5 │ const │ 38 │ Using index │
└────┴─────────────┴────────────┴───────┴───────────────┴────────┴─────────┴────────┴──────┴─────────────┘

Выполнение операторов SELECT в консоли SQL работает отлично и очень быстро.
Проблема
Это меняется, когда я использую PHP для выполнения запроса. В зависимости от API подключения к базе данных (например, mysqli, PDO) моя база данных решает не использовать индекс для моего представления, используя тот же запрос, что и раньше:
┌────┬─────────────┬────────────┬───────┬───────────────┬────────┬─────────┬─────┬──────────┬─────────────┐
│ id │ select_type │ table │ type │ possible_keys │ key │ key_len │ ref │ rows │ Extra │
╞════╪═════════════╪════════════╪═══════╪═══════════════╪════════╪═════════╪═════╪══════════╪═════════════╡
│ 1 │ PRIMARY │ │ ALL │ │ │ │ │ 56247595 │ Using where │
│ 2 │ DERIVED │ table1 │ index │ │ my_idx │ 5 │ │ 34706361 │ Using index │
│ 3 │ UNION │ table2 │ index │ │ my_idx │ 5 │ │ 21541234 │ Using index │
└────┴─────────────┴────────────┴───────┴───────────────┴────────┴─────────┴─────┴──────────┴─────────────┘

Отладка
Моя отладка показала, что следующие комбинации используют индекс ( ✅) или не используют индекс (❌):




API
кодировка
дополнительно (методы/опции)




✅
mysqli
latin1 (по умолчанию)
->execute_query($sql, [$type])


❌
mysqli
latin1 (по умолчанию)
->prepare(); ->bind_param(); ->execute(); ->get_result()


❌
mysqli
->set_charset('utf8mb4')
->execute_query($sql, [$type])


❌
mysqli
->set_charset('utf8mb4')
->prepare(); ->bind_param(); ->execute(); ->get_result()


✅
PDO
latin1 (по умолчанию)
ATTR_EMULATE_PREPARES = true (по умолчанию)


✅
PDO
latin1 (по умолчанию)
->setAttribute(PDO::ATTR_EMULATE_PREPARES, false)


✅
PDO
new PDO("...charset=utf8mb4", ...)
ATTR_EMULATE_PREPARES = true (по умолчанию)


❌
PDO
new PDO("...charset=utf8mb4", ...)
->setAttribute(PDO::ATTR_EMULATE_PREPARES, false)



Я не могу понять смысла этого. Что здесь происходит?
Информация о версии
  • MariaDB 10.6.18
    < li>PHP 8.2.26
Изменить (03.12.2024):
Выполнение EXPLAIN EXTENDED SELECT ... и SHOW WARNINGS впоследствии также дают тот же результат для всех тестов:
┌───────┬──────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Level │ Code │ Message │
├───────┼──────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Note │ 1003 │ /* select#1 */ select `my_view`.`type` AS `type` from `my_database`.`my_view` where `my_view`.`type` = 1 │
└───────┴──────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────┘


Подробнее здесь: https://stackoverflow.com/questions/792 ... ng-charset
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»