Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье приводятся рекомендации по написанию запросов GQL (язык запросов Graph), которые выполняются прогнозируемо и эффективно при работе с графом в Microsoft Fabric. Рекомендации основаны на текущем поведении платформы и документированных ограничениях.
Сведения о жестких ограничениях на размер графа, размер результата и время ожидания запроса см. в разделе "Текущие ограничения". Несколько рекомендаций в этой статье также связаны с тем, как вы разрабатываете схему графа. Дополнительные сведения см. в разделе "Проектирование схемы графа".
Ранняя фильтрация в шаблонах
Поместите фильтры внутри шаблонов графа, а не в последующих инструкциях. Предложения уровня WHERE шаблона сокращают количество промежуточных результатов перед выполнением соединений и последующими инструкциями, что снижает общие затраты на выполнение.
Рекомендуется: Фильтруйте во время сопоставления шаблонов.
-- Pattern-level WHERE reduces intermediate results
MATCH (p:Person WHERE p.birthday < 19940101)-[:workAt]->(c:Company WHERE c.id > 1000)
RETURN p.firstName, p.lastName, c.name
Избегайте: поздней фильтрации с использованием отдельного оператора FILTER.
-- Statement-level filter runs after all pattern matches are produced
MATCH (p:Person)-[:workAt]->(c:Company)
FILTER p.birthday < 19940101 AND c.id > 1000
RETURN p.firstName, p.lastName, c.name
Оба запроса возвращают одинаковые результаты, но первая версия позволяет обработчику запросов обрезать строки ранее в процессе оценки.
Подсказка
Думайте о уровне WHERE шаблона как аналогично условию SQL JOIN ... ON . Он ограничивает совпадения на этапе оценки, а не после фильтрации всего результирующего набора.
Возвращает только необходимые свойства
Возвращайте только те свойства узла и ребра, которые требуются вашим сценарием. Избегайте возврата полных узлов или использования RETURN * , если требуется только подмножество свойств.
В графе таблицы OneLake поддерживают свойства узлов. При выборе ненужных свойств увеличиваются объемы данных для чтения, расходы на сериализацию и размер ответа. Во время моделирования графа вручную выберите столбцы из исходной таблицы, которую необходимо добавить в качестве свойств типа узла.
Рекомендуется: Узкая проекция.
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name
Избегайте: Возврата полных узлов.
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN *
Замечание
Добавляйте только свойства типа узла во время моделирования графа, если они необходимы для запросов или анализа. Меньшее количество свойств на узел уменьшает как нагрузку на хранилище, так и нагрузку на запросы.
Ограничение размера результирующих наборов
При запросе узлов или связей, которые могут иметь высокую кратность, используйте LIMIT или другие ограничивающие условия. Неограниченные совпадения графа могут создавать очень большие множества результатов, которые приближаются к ограничениям платформы.
Рекомендуется: Ограниченные результаты.
MATCH (p:Person)-[:knows]->(friend:Person)
RETURN p.firstName, friend.firstName
LIMIT 1000
Избежать: Неограниченное совпадение с высокой кардинальностью.
MATCH (p:Person)-[:knows]->(friend:Person)
RETURN p.firstName, friend.firstName
Это важно
Обрезка ответов графа происходит, если их размер превышает 64 МБ, и производительность агрегации может быть нестабильной, если результаты превышают 128 МБ. Используйте FILTER, LIMIT и GROUP BY, чтобы сохранить результаты в пределах этих границ. Дополнительные сведения см. в разделе "Текущие ограничения".
Держите обходы поверхностными и направленными
Избегайте глубоко вложенных или очень сложных шаблонов графов. Используйте простые, целевые обходы, которые напрямую отвечают на конкретный вопрос. Каждый дополнительный прыжок в шаблоне переменной длины может экспоненциально увеличить количество путей, вычисляемых подсистемой, особенно в плотно подключенных графах.
Рекомендуется: Жёсткие ограничения.
-- Use the narrowest hop range that answers your question
MATCH (p:Person)-[:knows]->{1,3}(friend:Person)
RETURN p.firstName, friend.firstName
LIMIT 1000
Избегать: максимальной глубины обхода, если нет четкой необходимости.
-- Exploring the full 8-hop limit on a dense graph is expensive
MATCH (p:Person)-[:knows]->{1,8}(friend:Person)
RETURN *
Это важно
Graph поддерживает до восьми прыжков в шаблонах переменной длины. Даже в этом случае используйте самые строгие границы вашего сценария. В примере {1,3} шаблон значительно дешевле, чем {1,8} на том же графике.
Использование TRAIL для предотвращения избыточных обходов
Используйте режим обхода TRAIL для предотвращения повторного прохождения одного и того же ребра движком запросов. В плотных графах циклы могут привести к экспоненциальному увеличению числа путей.
TRAIL гарантирует, что каждый край просматривается не более одного раза за путь, что повышает правильность и производительность.
-- TRAIL prevents revisiting the same :knows edge
MATCH TRAIL (src:Person)-[:knows]->{1,4}(dst:Person)
WHERE src.firstName = 'Alice' AND dst.firstName = 'Bob'
RETURN count(*) AS numPaths
Без TRAIL этого один и тот же запрос на циклическом графе может создавать гораздо больший (и часто избыточный) результирующий набор.
Использование общих переменных для эффективных соединений
Если запросу требуются данные из нескольких связей, используйте общую переменную для объединения шаблонов в одной сущности. Без общей переменной шаблоны могут производить декартовый продукт - каждое сочетание совпадений из обоих шаблонов - что приводит к гораздо большему результирующем набору.
Рекомендуется: Общая переменная p присоединяет шаблоны.
-- Single shared variable ensures an efficient join
MATCH (p:Person)-[:workAt]->(c:Company),
(p)-[:isLocatedIn]->(city:City)
RETURN p.firstName, c.name AS company, city.name AS city
LIMIT 1000
Не используйте независимые шаблоны, не имеющие общую переменную.
-- Without a shared variable, this produces a cartesian product
MATCH (p1:Person)-[:workAt]->(c:Company),
(p2:Person)-[:isLocatedIn]->(city:City)
RETURN p1.firstName, c.name, p2.firstName, city.name
Декартово произведение соединяет каждый результат из одного шаблона с каждым результатом из другого. Если Person-workAt->Company соответствует 1000 строкам и Person-isLocatedIn->City соответствует 500 строкам, запрос возвращает 1000 × 500 = 500 000 строк. Добавление общей переменной ограничивает соединение, поэтому возвращаются только соответствующие пары.
Определение ограничений ключей на узлах
Определите ограничения ключа узла в типе графа. Ограничения ключей позволяют системе оптимизировать запросы, которые ищут определенные узлы по их ключевым свойствам, как и индексы первичного ключа в реляционных базах данных.
Например, если ваш тип графа определяет id в качестве ключа для узлов Person:
CONSTRAINT person_pk
FOR (n:Person) REQUIRE n.id IS KEY
Затем запросы, которые фильтруют по id, могут использовать этот ключ для прямого поиска.
-- Fast: the engine can look up person 12345 directly using the key
MATCH (p:Person WHERE p.id = 12345)-[:workAt]->(c:Company)
RETURN p.firstName, c.name
Без фильтра в свойстве ключа движок должен сканировать каждый Person узел.
-- Slower: scans all Person nodes before traversing
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, c.name
Подсказка
Если вам нужен определенный узел, отфильтруйте его ключевое свойство в шаблоне MATCH , чтобы воспользоваться заданным ограничением.
Выбор соответствующих типов данных
Выберите наиболее конкретный тип данных для каждого свойства во время моделирования графа. Выбор правильных типов важен как для эффективности хранения, так и для производительности запросов. Например, числовые сравнения свойств INT быстрее, чем сравнения строк по эквивалентным STRING значениям.
Сведения о поддерживаемых типах данных см. в разделе "Текущие ограничения" — типы данных и поддерживаемые типы свойств.
Объединение связанных обходов в одном запросе
По возможности извлекайте связанные сущности в одном шаблоне графа, вместо отправки отдельных запросов, которые проходят по тем же краям отдельно. Объединение обходов позволяет избежать сопоставления избыточных шаблонов и предотвращает проблему запроса N+1, при которой один начальный запрос активирует отдельный запрос для каждой строки результата.
Рекомендуется: Единый объединенный шаблон.
MATCH (c:Customer)-[:purchased]->(o:Order)-[:contains]->(product:Product)
RETURN c.id, o.id, product.name
LIMIT 1000
Избегайте: Два отдельных запроса, которые используют одно и то же Customer → Order ребро.
-- Query 1: fetch 100 orders
MATCH (c:Customer)-[:purchased]->(o:Order)
RETURN c.id, o.id
-- Query 2: run once per order to get products (N+1 problem)
MATCH (o:Order)-[:contains]->(product:Product)
RETURN o.id, product.name
Тестирование запросов к реалистичным томам данных
Запросы, которые хорошо выполняются в небольших наборах данных, могут не масштабироваться линейно. Проверьте запросы с помощью объемов данных, представляющих ожидаемую рабочую нагрузку.
- Предпочитайте консервативные фигуры запросов, включающие фильтры и ограничения.
- Избегайте разведочных запросов "возвращающие все" к большим графам.
- Отслеживайте длительность запроса относительно 20-минутного ограничения времени ожидания.