На моей работе мы работаем с базами данных (преимущественно MySQL 5.7.2, это то, что я не могу изменить). Обычно задача заключается в написании сложных запросов к наборам данных, состоящим из миллионов строк. Это делается с помощью потока запросов MySQL, строящихся друг над другом (каждый из которых является временной таблицей, со следующей временной таблицей, построенной на предыдущих и т. д.). Поскольку количество строк исчисляется миллионами, включая соединения с несколькими столбцами, для этих временных таблиц выполняется индексация с использованием операторов alter table.
Теперь, когда я пытаюсь понять, как использовать dplyr и изучить возможности каналов, мне кажется, что это прекрасное решение для тех проблем, которые мы решаем; т. е. запросы строятся друг над другом. Поэтому я написал простые сценарии, использующие возможности dplyr. Я отправляю все запросы обратно в MySQL, чтобы оценить конечный результат (конечный результат — всего несколько сотен строк). Таким образом, вся обработка будет выполняться на удаленном сервере MySQL без необходимости загрузки миллионов строк в локальный экземпляр R, и только набор результатов будет извлечен локальным экземпляром R.
Однако я столкнулся с узким местом, где требуется индексация; и это абсолютно необходимо из-за проблем с производительностью. Как я вижу, я могу использовать функцию copy_to в dplyr, которая дает мне возможность добавлять индексы; тут меня смущают две вещи:
Мне нужно создать новую таблицу на удаленном сервере MySQL для хранения результата copy_to (в большинстве сценариев нам разрешены только временные таблицы).
Даже если мне каким-то образом удастся написать постоянную таблицу, функция copy_to не позволит мне определить собственное имя индекса, как в MySQL; в то время как имя по умолчанию, которое он придумал, слишком длинное для MySQL (выдает ошибки по длине имени индекса).
Мы будем очень признательны за любые советы по использованию индексов с dplyr. В идеале я хочу что-то вроде того, что показано в смелый ниже:
Tbl1 %>% filter(...) %>% mutate(...) %>% left_join(Tbl2, by("col1" = "col1", "col2" = "col2") %>% add_index(col_from_tbl1, col_from_tbl2) %> % другие операции
Кстати, я вижу, что решение для длинного имени индекса состоит в том, чтобы копировать_в новую таблицу; затем используйте DBI::dbSendQuery, чтобы добавить индекс с именем по моему выбору; это работает. Однако потребность в индексации возникает очень часто. Из-за этого элегантность использования каналов исчезает, так как мне нужно остановиться в середине цепочки каналов, скопировать_в новую таблицу, а затем добавить индекс с помощью dbSendQuery; а затем снова начать использовать трубы. Весь смысл иметь хорошо читаемый код исчезает.
Конвейерная обработка и использование множества временных таблиц в последовательности — это способ значительно замедлить весь процесс. Попробуйте написать один оператор SQL. Как и в большинстве сторонних пакетов, базовый SQL является ключом к производительности; пакет может действительно мешать.
Спасибо @RickJames. Это имеет смысл. Тем не менее, я по-прежнему вижу преимущества этого пути: 1) быстрое построение запроса 2) легко понять 3) более надежный в случаях, когда нам нужно использовать запрос для нескольких анализов, а затем отбросить (предварительное время, необходимое для планирование более сложного отдельного оператора сохраняется; в любом случае, для посредственного автора SQL-запросов).
Что ж, изучите запросы и временные таблицы, которые dplyr строит для вас. Вскоре вы освоитесь и будете готовы бросить dplyr. (Я трачу слишком много времени, помогая программистам на этом форуме устранять недостатки сторонних пакетов, которые «помогают» им избежать изучения SQL.)






Pasteиpaste0могут подойти вам, а также естьsprintf. Я вижу, что, поскольку вы используете функциюTidyverseвdplyr, вы можете обнаружить, чтоglueлучше.