Подтвердить что ты не робот

MySQL количество элементов в разделе "in"

У меня есть три таблицы для определения пользователей:

USER: user_id (int), username (varchar)
USER_METADATA_FIELD: user_metadata_field_id (int), field_name (varchar)
USER_METADATA: user_metadata_field_id (int), user_id (int), field_value (varchar)

Я хотел бы создать пользователя среднего уровня, который имеет определенный доступ к другим пользователям в приложении. Чтобы определить, к каким пользователям, которые вошли в систему, могут получить доступ, я использую подзапрос, как показано ниже:

SELECT user_id FROM user WHERE user_id 
     IN (SELECT user_id 
         FROM user_metadata 
         WHERE user_metadata_field_id = 1 AND field_value = 'foo')

В настоящее время я сохраняю строку подзапроса в переменной, а затем динамически вставляю ее во внешний запрос каждый раз, когда мне нужно вывести список пользователей. После этого я подумал: "Лучше всего просто сохранить строку фактического user_id s".

Итак, вместо сохранения этого в переменной...

$subSql = "SELECT user_id FROM user_metadata WHERE user_metadata_field_id = 1 AND field_value = 'foo'";

... Я действительно выполняю запрос и сохраняю результат следующим образом:

$subSql = "12, 56, 89, 100, 1234, 890";

Затем, когда мне нужно вытащить освещенных пользователей, к которым имеет доступ зарегистрированный пользователь, я могу сделать это с помощью

$sql = "SELECT user_id FROM user WHERE user_id IN ($subSql)";

И, наконец, вопросы:

Сколько элементов вы можете использовать в MySQL IN CLAUSE? Сохранение фактических идентификаторов вместо оператора sub-sql должно выполняться быстрее для выполнения этого внешнего запроса каждый раз, правильно?

4b9b3361

Ответ 1

Начиная с определенного числа, таблицы IN выполняются быстрее.

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

См. эту статью в своем блоге для подробностей о производительности:

Ответ 2

Из руководства :

Количество значений в списке IN ограничено только значением max_allowed_packet.

Ответ 3

Как указано в ответе Quassnoi, один сталкивается с другими практическими соображениями, прежде чем нанести любой возможный предел, наложенный данной версией версии MySql (*). Таким образом, по мере увеличения количества пользователей-администраторов (или других критериев, которые могут потребовать конструкцию IN), следует искать альтернативы буквальному "IN", например, использование временных (или даже постоянных) таблиц.

Поскольку вы рассматриваете специальную обработку критериев "admin user", для целей производительности я хотел бы предложить комментарий и предложение.

Комментарий: Может ли это быть причиной преждевременной оптимизации?
Я не осознаю специфику этой базы данных, ее объем, сложность и т.д. И да, я знаю о какой-то отдаче за производительность, которую нужно уделить формату EAV (Entity-Attribute-Value), но я думаю, что даже для успешных предприятий база данных учетных записей редко насчитывает более 10 000 пользователей. Таким образом, даже с очень большим количеством атрибутов для каждого пользователя мы все еще смотрим на относительно небольшую таблицу EAV, которая может не потребовать такого типа оптимизации. (С другой стороны, в других областях можно приветствовать несколько других трюков оптимизации). Кроме того, типичные случаи использования включают относительно небольшое количество запросов в базу данных учетных записей по сравнению с другими запросами, и поэтому это еще одна причина для деффер любое нетривиальное рассмотрение производительности для связанных с учетной записью функций приложения.

Предложение: Возможно использование "переопределенных атрибутов"
Для атрибутов, которые являются однозначными и, в частности, если они коротки, их можно перемещать (или дублировать) в таблице Entity (в этом случае таблица USER). Это вводит немного логики при вставке или обновлении элементов времени, но это приводит к множеству объединений (или подзапросов), а также предоставляет возможность рассматривать многополевые индексы для поддержки наиболее распространенных случаев использования.

(*) Существует ли limt? Я не читал о таком лимите; Я знаю, что Oracle имеет (имел) 1000 лимит в течение некоторого времени, MSSQL этого не делает; конечно, все серверы имеют ограничение, основанное на общей длине инструкции SQL, но это действительно большое число! если кто-то наткнется на него, у него будут другие проблемы...;-)

Ответ 4

У MySQL IN Clause нет такого ограничения. Я пробовал с 8000 элементов, его работа отлично для меня. Ошибка может быть объявлена ​​переменной,