github
description: 'Набор данных, содержащий все коммиты и изменения для репозитория ClickHouse' slug: /getting-started/example-datasets/github sidebar_label: Github Repo sidebar_position: 1 title: 'Написание запросов в ClickHouse, используя данные GitHub'
Это займет около 3 минут (на 8 ноября 2022 года на MacBook Pro 2021) для завершения для репозитория ClickHouse.
Полный список доступных опций можно получить из встроенной помощи инструмента.
Эта помощь также предоставляет DDL для каждой из вышеупомянутых таблиц например:
Эти запросы должны работать с любым репозиторием. Не стесняйтесь исследовать и сообщать о своих результатах Некоторые рекомендации относительно времени выполнения (на ноябрь 2022 года):
- Linux -
~/clickhouse git-import
- 160 минут
Скачивание и вставка данных
Следующие данные можно использовать для воспроизведения рабочей среды. Кроме того, этот набор данных доступен на play.clickhouse.com - смотрите Запросы для получения дополнительной информации.
Сгенерированные файлы для следующих репозиториев можно найти ниже:
- ClickHouse (8 ноября 2022 года)
- https://datasets-documentation.s3.amazonaws.com/github/commits/clickhouse/commits.tsv.xz - 2.5 MB
- https://datasets-documentation.s3.amazonaws.com/github/commits/clickhouse/file_changes.tsv.xz - 4.5MB
- https://datasets-documentation.s3.amazonaws.com/github/commits/clickhouse/line_changes.tsv.xz - 127.4 MB
- Linux (8 ноября 2022 года)
Чтобы вставить эти данные, подготовьте базу данных, выполнив следующие запросы:
Вставьте данные с использованием INSERT INTO SELECT
и функции s3. Например, ниже мы вставляем файлы ClickHouse в каждую из их соответствующих таблиц:
commits
file_changes
line_changes
Запросы
Инструмент предлагает несколько запросов через свои вывод помощи. Мы ответили на них в дополнение к некоторым дополнительным вспомогательным вопросам интереса. Эти запросы имеют примерно возрастающую сложность по сравнению с произвольным порядком инструмента.
Этот набор данных доступен на play.clickhouse.com в базах данных git_clickhouse
. Мы предоставляем ссылку на эту среду для всех запросов, адаптируя имя базы данных по мере необходимости. Обратите внимание, что результаты игры могут отличаться от представленных здесь из-за различий во времени сбора данных.
История одного файла
Самый простой из запросов. Здесь мы смотрим на все сообщения коммитов для StorageReplicatedMergeTree.cpp
. Поскольку они, вероятно, более интересны, мы сортируем по самым недавним сообщениям сначала.
Мы также можем просмотреть изменения строк, исключая переименования, то есть мы не покажем изменения до события переименования, когда файл существовал под другим именем:
Обратите внимание, что существует более сложный вариант этого запроса, в котором мы находим историю коммитов построчно для файла, учитывая переименования.
Найти текущие активные файлы
Это важно для последующего анализа, когда мы хотим учитывать только текущие файлы в репозитории. Мы оцениваем этот набор как файлы, которые не были переименованы или удалены (а затем повторно добавлены/переименованы).
Обратите внимание, что, похоже, была нарушена история коммитов в отношении файлов в директориях dbms
, libs
, tests/testflows/
во время их переименований. Поэтому мы также исключаем их.
Обратите внимание, что это позволяет файлам переименовываться, а затем снова переименовываться в их первоначальные значения. Сначала мы агрегируем old_path
для списка удаленных файлов в результате переименования. Затем мы объединяем это с последней операцией для каждого path
. Наконец, мы фильтруем этот список на те, где конечное событие не является Delete
.
Обратите внимание, что мы пропустили импорт нескольких директорий во время импорта, то есть
--skip-paths 'generated\.cpp|^(contrib|docs?|website|libs/(libcityhash|liblz4|libdivide|libvectorclass|libdouble-conversion|libcpuid|libzstd|libfarmhash|libmetrohash|libpoco|libwidechar_width))/'
Применяя этот шаблон к git list-files
, количество файлов составляет 18155.
Наше текущее решение, следовательно, является оценкой текущих файлов
Разница здесь вызвана несколькими факторами:
- Переименование может происходить наряду с другими изменениями в файле. Эти изменения перечислены как отдельные события в
file_changes
, но с одинаковым временем. ФункцияargMax
не может отличить их - она выбирает первое значение. Естественный порядок вставок (единственное средство, чтобы знать правильный порядок) не поддерживается через объединение, поэтому могут быть выбраны измененные события. Например, ниже файлsrc/Functions/geometryFromColumn.h
имеет несколько модификаций до того, как он был переименован вsrc/Functions/geometryConverters.h
. Наше текущее решение может выбрать событие Modify как последнее изменение, что приводит к сохранениюsrc/Functions/geometryFromColumn.h
.
- Нарушенная история коммитов - отсутствие событий удаления. Источник и причина TBD.
Эти различия не должны существенно повлиять на наш анализ. Мы приветствуем улучшенные версии этого запроса.
Список файлов с наибольшим количеством модификаций
Ограничиваясь текущими файлами, мы считаем количество модификаций как сумму удалений и добавлений.
Какой день недели коммиты обычно происходят?
Это имеет смысл с некоторым снижением продуктивности в пятницу. Замечательно видеть, что люди коммитят код по выходным! Большое спасибо нашим участникам!
История подкаталога/файла - число строк, коммитов и участников с течением времени
Это приведет к большому результату запроса, который будет нереалистично показать или визуализировать, если он не отфильтрован. Поэтому мы позволяем фильтровать файл или подкаталог в следующем примере. Здесь мы группируем по неделям, используя функцию toStartOfWeek
- адаптируйте по мере необходимости.
Эти данные хорошо визуализируются. Ниже мы используем Superset.
Для добавленных и удаленных строк:
Для коммитов и авторов:
Список файлов с максимальным количеством авторов
Ограничьтесь только текущими файлами.
Самые старые строки кода в репозитории
Ограничено только текущими файлами.
Файлы с самой длинной историей
Ограничено только текущими файлами.
Наша основная структура данных, Merge Tree, очевидно, находится в постоянной эволюции с долгой историей изменений!
Распределение участников в отношении документации и кода за месяц
Во время захвата данных изменения в папке docs/
были отфильтрованы из-за очень запутанной истории коммитов. Результаты этого запроса, следовательно, неточные.
Пишем ли мы больше документации в определенные периоды месяца, например, вблизи дат релизов? Мы можем использовать функцию countIf
, чтобы вычислить простое соотношение, визуализировав результат с помощью функции bar
.
Возможно, немного больше в конце месяца, но в целом мы сохраняем хорошее равномерное распределение. Вновь, это ненадежно из-за фильтрации папки docs во время вставки данных.
Авторы с наиболее разнообразным влиянием
Мы считаем разнообразие здесь как количество уникальных файлов, к которым автор внес свой вклад.
Давайте посмотрим, у кого самые разнообразные коммиты в недавней работе. Вместо ограничения по дате, мы ограничим количество последних коммитов автора (в данном случае мы использовали 3, но не стесняйтесь изменять):
Любимые файлы автора
Здесь мы выбираем нашего основателя Alexey Milovidov и ограничиваем наш анализ текущими файлами.
Это имеет смысл, потому что Алексей отвечает за поддержание журнала изменений. Но что если мы используем базовое имя файла, чтобы определить его популярные файлы - это позволяет учитывать переименования и должно сосредоточиться на кодовых вложениях.
Это может быть более отражающим его области интересов.
Самые большие файлы с наименьшим количеством авторов
Для этого мы сначала должны определить самые большие файлы. Оценка этого через полное восстановление файла, для каждого файла, на основе истории коммитов, будет очень дорогой!
Чтобы оценить, предполагая, что мы ограничиваемся текущими файлами, мы суммируем добавленные строки и вычитаем удаленные. Затем мы можем вычислить соотношение длины к количеству авторов.
Текстовые словари могут быть не очень реалистичными, поэтому давайте ограничим только код через фильтр по расширению файла!
Существует некоторая предвзятость к новизне в этом - новые файлы имеют меньше возможностей для коммитов. А что, если мы ограничим файлы как минимум старше 1 года?
Коммиты и строки кода распределение по времени; по дню недели, по автору; для конкретных подсрок
Мы интерпретируем это как количество строк, добавленных и удалённых по дням недели. В данном случае мы фокусируемся на каталоге Functions
А по времени суток,
Это распределение имеет смысл, учитывая, что большая часть нашей команды разработки находится в Амстердаме. Функция bar
позволяет нам визуализировать эти распределения:
Матрица авторов, показывающая, какие авторы переписывают код других авторов
sign = -1
указывает на удаление кода. Мы исключаем пунктуацию и вставку пустых строк.
Диаграмма Санки (SuperSet) позволяет визуализировать это удобно. Обратите внимание, что мы увеличиваем наш LIMIT BY
до 3, чтобы получить тройку главных удалителей кода для каждого автора, чтобы улучшить разнообразие в визуализации.
Алексей явно любит удалять код других людей. Давайте исключим его для более сбалансированного взгляда на удаление кода.
Кто является автором с наибольшим процентом вклада по дням недели?
Если мы учитываем просто количество коммитов:
Хорошо, есть некоторые возможные преимущества здесь для самого длительного автора - нашего основателя Алексея. Давайте ограничим наш анализ последним годом.
Это всё еще немного просто и не отражает работы людей.
Лучшим показателем может являться то, кто является ключевым вкладчиком в каждый день в процентном соотношении от общего объёма работы, выполненной за прошлый год. Обратите внимание, что мы рассматриваем удаление и добавление кода на равных.
Распределение возраста кода по репозиторию
Мы ограничиваем анализ текущими файлами. Для краткости мы ограничиваем результаты до глубины 2 с 5 файлами на корневую папку. Настройте по мере необходимости.
Какой процент кода автором был удалён другими авторами?
Для этого вопроса нам нужно количество строк, написанных автором, разделенное на общее количество строк, которые были удалены другим участником.
Перечислите файлы, которые были переписаны наибольшее количество раз?
Самый простой подход к этому вопросу может заключаться в том, чтобы просто посчитать наибольшее количество изменений строк по пути (ограниченным текущими файлами), например:
Это не фиксирует понятие "перезаписи", однако, когда большая часть файла изменяется в любом коммите. Это требует более сложного запроса. Если вы считаете перезапись, когда более 50% файла удалено и 50% добавлено. Вы можете отрегулировать запрос в соответствии с вашей интерпретацией того, что это подразумевает.
Запрос ограничен только текущими файлами. Мы перечисляем все изменения файлов, группируя по path
и commit_hash
, возвращая количество добавленных и удалённых строк. Используя оконную функцию, мы оцениваем общий размер файла в любой момент времени, выполняя кумулятивную сумму и оценивая влияние каждого изменения на размер файла как строки добавлены - строки удалены
. Используя эту статистику, мы можем рассчитать процент файла, который был добавлен или удалён для каждого изменения. Наконец, мы подсчитываем количество изменений файла, которые составляют переписывание на файл т.е. (процент добавления >= 0.5) AND (процент удаления >= 0.5) AND текущий размер > 50
. Обратите внимание, что мы требуем, чтобы файлы содержали более 50 строк, чтобы избежать ранних вкладов в файл, которые могут быть учтены как перезапись. Это также избегает предвзятости очень маленьких файлов, которые могут быть более склонны к переписыванию.
В какой день недели код имеет наибольшую вероятность остаться в репозитории?
Для этого нам нужно уникально идентифицировать строку кода. Мы оцениваем это (так как одна и та же строка может появиться несколько раз в файле) по пути и содержимому строки.
Мы запрашиваем строки, добавленные, соединяя это с удалёнными строками - фильтруя случаи, когда последнее происходит более поздним, чем первое. Это даёт нам удаленные строки, из которых мы можем вычислить время между этими двумя событиями.
Наконец, мы агрегируем по этому набору данных, чтобы вычислить среднее количество дней, которые строки остаются в репозитории по дням недели.
Файлы, отсортированные по среднему возрасту кода
Этот запрос использует тот же принцип, что и В какой день недели код имеет наибольшую вероятность остаться в репозитории - пытаясь уникально идентифицировать строку кода, используя путь и содержимое строки. Это позволяет нам определить время между добавлением и удалением строки. Однако мы фильтруем только текущие файлы и код, а затем берем среднее время для каждого файла по строкам.
Кто, как правило, пишет больше тестов / кода / комментариев на C++?
Существует несколько способов подойти к этому вопросу. Сосредоточившись на соотношении кода к тестам, этот запрос относительно прост - подсчитайте количество вкладов в папки, содержащие tests
, и вычислите отношение к общему количеству вкладов.
Обратите внимание, что мы ограничиваем пользователей более чем 20 изменениями, чтобы сосредоточиться на регулярных коммитерах и избежать предвзятости к одноразовым вкладам.
Мы можем изобразить это распределение в виде гистограммы.
Большинство участников пишут больше кода, чем тестов, как и следовало ожидать.
Что насчет тех, кто добавляет больше всего комментариев при внесении кода?
Обратите внимание, что мы сортируем по вкладкам кода. Удивительно высокая доля для всех наших крупнейших участников - это часть того, что делает наш код таким читаемым.
Как изменяются коммиты авторов с течением времени с точки зрения процента кода/комментариев?
Чтобы вычислить это по авторам, это просто,
Однако, в идеале, мы хотим увидеть, как это изменяется в агрегированном виде по всем авторам с первого дня их коммитов. Уменьшают ли они постепенно количество комментариев, которые они пишут?
Чтобы вычислить это, мы сначала вычисляем соотношение комментариев для каждого автора по времени - аналогично Кто, как правило, пишет больше тестов / кода / комментариев?. Это соединяется с датой начала каждого автора, что позволяет нам вычислить соотношение комментариев по недельным интервалам.
После вычисления среднего по неделе для всех авторов, мы выбираем эти результаты, выбрав каждую 10-ю неделю.
Обнадеживает то, что наш процент комментариев довольно постоянен и не ухудшается на протяжении долгого времени, пока авторы вносят изменения.
Каково среднее время до перезаписи кода и медиана (период полураспада кода)?
Мы можем использовать тот же принцип, что и Список файлов, которые были переписаны наибольшее количество раз или большинством авторов, чтобы идентифицировать переписывания, но учитывать все файлы. Используется оконная функция для вычисления времени между переписываниями для каждого файла. На основе этого мы можем вычислить среднее и медиану по всем файлам.
Каково наихудшее время для написания кода с точки зрения того, что код имеет наибольшую вероятность переписывания?
Похоже на Каково среднее время до перезаписи кода и медиана (период полураспада кода)? и Список файлов, которые были переписаны наибольшее количество раз или большинством авторов, за исключением того, что мы агрегируем по дням недели. При необходимости отрегулируйте, например, по месяцам года.
Код какого автора самый «липкий»?
Мы определяем «липкий» как то, как долго код автора остается, прежде чем его перепишут. Похоже на предыдущий вопрос Каково среднее время до перезаписи кода и медиана (период полураспада кода)? - используя тот же критерий для переписываний, т.е. 50% добавлений и 50% удалений файлов. Мы вычисляем среднее время переписывания по автору и учитываем только вкладчиков с более чем двумя файлами.
Наибольшее количество последовательных дней коммитов автором
Этот запрос сначала требует от нас вычислить дни, когда автор совершал коммиты. Используя оконную функцию, разбивая по авторам, мы можем вычислить дни между их коммитами. Для каждого коммита, если время с последнего коммита составляет 1 день, мы помечаем это как последовательное (1), а в противном случае - 0 - сохраняя этот результат в consecutive_day
.
Наши последующие функции массивов вычисляют самую длинную последовательность последовательных единиц для каждого автора. Сначала используется функция groupArray
, чтобы собрать все значения consecutive_day
для автора. Этот массив из 1 и 0 затем разбивается по значениям 0 в подмассивы. Наконец, мы вычисляем самую длинную подмассив.
История коммитов файла построчно
Файлы могут быть переименованы. Когда это происходит, мы получаем событие переименования, где колонка path
установлена на новый путь файла, а old_path
представляет собой предыдущее местоположение, например:
Это делает просмотр полной истории файла сложным, поскольку у нас нет единственного значения, связывающего все изменения строк или файлов.
Чтобы решить эту проблему, мы можем использовать пользовательские функции (UDF). В настоящее время они не могут быть рекурсивными, поэтому, чтобы определить историю файла, мы должны определить серию UDF, которые будут вызывать друг друга явно.
Это означает, что мы можем отслеживать переименования лишь до определенной глубины — приведенный ниже пример имеет глубину 5. Маловероятно, что файл будет переименован большее количество раз, поэтому на данный момент этого достаточно.
Вызывая file_path_history('src/Storages/StorageReplicatedMergeTree.cpp')
, мы рекурсивно проходим через историю переименования, где каждая функция вызывает следующий уровень с old_path
. Результаты объединяются с помощью arrayConcat
.
Например,
Мы можем использовать эту возможность, чтобы теперь собрать коммиты для всей истории файла. В этом примере мы показываем один коммит для каждого из значений path
.
Неразрешенные вопросы
Git blame
Это особенно сложно, чтобы получить точный результат из-за невозможности в настоящее время сохранять состояние в функциях массива. Это будет возможно с помощью arrayFold
или arrayReduce
, которые позволяют хранить состояние на каждой итерации.
Приблизительное решение, достаточное для анализа на высоком уровне, может выглядеть примерно так:
Мы приветствуем точные и улучшенные решения здесь.