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_ids".

поэтому вместо того чтобы хранить это в переменную...

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

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

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

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

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

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

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

4 56

4 ответа:

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

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

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

С руководство:

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

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

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

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

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

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

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