SAMPLE / SAMPLE BLOCK в Oracle SQL: случайная выборка блоков данных

🟢 SAMPLE / SAMPLE BLOCKв Oracle SQL. Введение

SAMPLE / SAMPLE BLOCK — это возможность Oracle SQL выбирать случайную подвыборку строк из таблицы.
Синтаксис позволяет управлять долей (в процентах) и воспроизводимостью через SEED.
Опция BLOCK использует блочное (по экстентам) семплирование — быстрее на больших таблицах, но менее равномерно на уровне отдельных строк.

Где используют

  • Быстрая разведка данных: получить представление о распределениях без полного скана.
  • Дешёвые проверки гипотез: тестировать JOIN‑ы, фильтры и агрегаты на подмножестве.
  • Прототипы визуализаций: отрисовать графики и отчёты на подвыборке.
  • Тесты производительности: сравнить планы запросов на частях данных.

Синтаксис

SELECT ...
FROM table_name [ t ]
  SAMPLE [ BLOCK ] ( percentage )
  [ SEED ( seed_value ) ]
[ WHERE ... ]
  • percentage — доля строк (0.000001 … 100);
  • SEED — фиксирует генератор (одинаковый результат для одинакового зерна, если данные стабильны);
  • BLOCK — быстрее на больших таблицах (читает целые блоки); может давать дисбаланс на мелких выборках.

Примечания: семпл выбирается на этапе доступа к таблице; семплирование нескольких таблиц независимо; проценты — ориентировочные.

100 примеров

1. Базовая случайная подвыборка 1%

SELECT *
FROM customers SAMPLE (3);

2. Блочное семплирование 10% для логов

SELECT *
FROM app_logs SAMPLE BLOCK (10);

3. Фиксируем результат через SEED(42)

SELECT *
FROM transactions SAMPLE (10) SEED (42);

4. Семпл и фильтр в WHERE

SELECT order_id, amount
FROM orders SAMPLE (10)
WHERE status = 'PAID';

5. Подвыборка и агрегаты в GROUP BY

SELECT country, COUNT(*) AS cnt
FROM customers SAMPLE (15)
GROUP BY country;

6. Семпл в JOIN: семплируем только левую таблицу

SELECT o.order_id, c.customer_name
FROM orders SAMPLE (20) o
JOIN customers c ON c.customer_id = o.customer_id;

7. Семпл в JOIN обеих таблиц

SELECT o.order_id, c.segment
FROM orders SAMPLE (1) o
JOIN customers SAMPLE (10) c ON c.customer_id = o.customer_id;

8. Подвыборка с ORDER BY и ограничением результата

SELECT *
FROM products SAMPLE (2)
ORDER BY created_at
FETCH FIRST 100 ROWS ONLY;

9. Блочное семплирование на партиционированной таблице

SELECT *
FROM sales_part SAMPLE BLOCK (20)
WHERE sales_date >= DATE '2025-01-01';

10. Репликация результата: одинаковый SEED

SELECT COUNT(*) AS n1
FROM events SAMPLE (1) SEED (100);
-- Перезапуск с тем же SEED даст ту же мощность выборки (при неизменных данных)

11. Вложенный подзапрос: семплируем подтаблицу

SELECT product_id, SUM(amount) AS total
FROM (
  SELECT product_id, amount
  FROM sales SAMPLE (20)
) s
GROUP BY product_id;

12. Семпл и DISTINCT

SELECT DISTINCT country
FROM customers SAMPLE (2);

13. Оценка среднего чека по подвыборке

SELECT AVG(amount) AS avg_check
FROM orders SAMPLE (10);

14. Семпл по большим таблицам — блочный режим

SELECT *
FROM pageviews SAMPLE BLOCK (20)
WHERE url LIKE '/docs/%';

15. Стабильная доля по ключу (альтернатива)

SELECT *
FROM orders
WHERE MOD(ORA_HASH(customer_id), 100) < 5;

16. Сравнение двух долей подвыборки

SELECT 'small' AS tag, COUNT(*) AS n FROM orders SAMPLE (1)
UNION ALL
SELECT 'big'   AS tag, COUNT(*) AS n FROM orders SAMPLE (1);

17. Выборка и WINDOW‑аналитика

SELECT
  customer_id,
  SUM(amount) OVER (PARTITION BY customer_id) AS total_by_customer
FROM orders SAMPLE (0.5);

18. Семпл и подмножество колонок

SELECT customer_id, created_at, country
FROM customers SAMPLE (7);

19. Проверка гипотезы JOIN‑качества на подвыборке

SELECT COUNT(*) AS matches
FROM orders SAMPLE (20) o
JOIN shipments s ON s.order_id = o.order_id;

20. Бенчмарк — сравнить планы на подвыборке

EXPLAIN PLAN FOR
SELECT /* test */ * FROM big_table SAMPLE (2);
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

Еще 20 примеров.

21. Блочное семплирование 20% с SEED

SELECT *
FROM app_logs SAMPLE BLOCK (20) SEED (77);

22. Фиксированная подвыборка для отчёта дня

SELECT *
FROM transactions SAMPLE (3) SEED (TO_NUMBER(TO_CHAR(SYSDATE,'J')));

23. Подвыборка и HAVING по сумме

SELECT product_id, SUM(amount) AS total
FROM sales SAMPLE (0.1)
GROUP BY product_id
HAVING SUM(amount) > 1000;

24. Семпл в правой таблице JOIN

SELECT e.emp_id, d.dept_name
FROM employees e
JOIN departments SAMPLE (5) d ON d.dept_id = e.dept_id;

25. Семпл с типичным WHERE‑фильтром

SELECT *
FROM sessions SAMPLE (1)
WHERE device = 'mobile' AND country = 'DE';

26. Вложенный UNION ALL c семплом в каждом плече

SELECT 'A' src, COUNT(*) n FROM a SAMPLE (20)
UNION ALL
SELECT 'B' src, COUNT(*) n FROM b SAMPLE (10);

27. Подвыборка для визуализации временного ряда

SELECT ts, metric
FROM metrics SAMPLE (8)
WHERE ts >= SYSTIMESTAMP - INTERVAL '7' DAY;

28. Сэмпл и вычисляемые поля

SELECT order_id, amount, amount*0.2 AS vat
FROM orders SAMPLE (0.1);

29. Блочный режим для больших архивов

SELECT *
FROM archive_audit SAMPLE BLOCK (10);

30. Разные SEED для сравнения стабильности

SELECT COUNT(*) n FROM t SAMPLE (20) SEED (1);
SELECT COUNT(*) m FROM t SAMPLE (1) SEED (2);

31. Подвыборка и оконная медиана

SELECT
  PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS p50
FROM orders SAMPLE (0.5);

32. Семпл перед материализацией во временную таблицу

CREATE GLOBAL TEMPORARY TABLE tmp_orders AS
SELECT * FROM orders SAMPLE (20);

33. Сэмпл и удаление дубликатов

SELECT DISTINCT customer_id
FROM orders SAMPLE (15);

34. Фиксируем дневной SEED от даты

SELECT *
FROM big_table SAMPLE (15) SEED (TO_NUMBER(TO_CHAR(CURRENT_DATE,'DDD')));

35. Подвыборка с сортировкой по времени

SELECT *
FROM events SAMPLE (15)
ORDER BY event_ts DESC;

36. Семпл в подзапросе внутри WHERE IN

SELECT *
FROM customers
WHERE customer_id IN (
  SELECT customer_id
  FROM orders SAMPLE (3)
);

37. Подвыборка для быстрой валидации схемы

SELECT table_name, column_name, data_type
FROM user_tab_columns SAMPLE (20);

38. Блочный режим на партиции за месяц

SELECT *
FROM sales_2025_01 SAMPLE BLOCK (12);

39. Сэмпл и вычисление DISTINCT‑количества

SELECT COUNT(DISTINCT customer_id) AS dc
FROM orders SAMPLE (12);

40. Прототип отчёта: топ‑категории на подвыборке

SELECT category, SUM(amount) AS total
FROM sales SAMPLE (5)
GROUP BY category
ORDER BY total DESC
FETCH FIRST 10 ROWS ONLY;

Еще 20 примеров.

41. Базовая случайная подвыборка 1%

SELECT *
FROM customers SAMPLE (1);

42. Блочное семплирование 10% для логов

SELECT *
FROM app_logs SAMPLE BLOCK (25);

43. Фиксируем результат через SEED(42)

SELECT *
FROM transactions SAMPLE (3) SEED (42);

44. Семпл и фильтр в WHERE

SELECT order_id, amount
FROM orders SAMPLE (4)
WHERE status = 'PAID';

45. Подвыборка и агрегаты в GROUP BY

SELECT country, COUNT(*) AS cnt
FROM customers SAMPLE (20)
GROUP BY country;

46. Семпл в JOIN: семплируем только левую таблицу

SELECT o.order_id, c.customer_name
FROM orders SAMPLE (2) o
JOIN customers c ON c.customer_id = o.customer_id;

47. Семпл в JOIN обеих таблиц

SELECT o.order_id, c.segment
FROM orders SAMPLE (6) o
JOIN customers SAMPLE (15) c ON c.customer_id = o.customer_id;

48. Подвыборка с ORDER BY и ограничением результата

SELECT *
FROM products SAMPLE (7)
ORDER BY created_at
FETCH FIRST 100 ROWS ONLY;

49. Блочное семплирование на партиционированной таблице

SELECT *
FROM sales_part SAMPLE BLOCK (15)
WHERE sales_date >= DATE '2025-01-01';

50. Репликация результата: одинаковый SEED

SELECT COUNT(*) AS n1
FROM events SAMPLE (5) SEED (100);
-- Перезапуск с тем же SEED даст ту же мощность выборки (при неизменных данных)

51. Вложенный подзапрос: семплируем подтаблицу

SELECT product_id, SUM(amount) AS total
FROM (
  SELECT product_id, amount
  FROM sales SAMPLE (10)
) s
GROUP BY product_id;

52. Семпл и DISTINCT

SELECT DISTINCT country
FROM customers SAMPLE (4);

53. Оценка среднего чека по подвыборке

SELECT AVG(amount) AS avg_check
FROM orders SAMPLE (5);

54. Семпл по большим таблицам — блочный режим

SELECT *
FROM pageviews SAMPLE BLOCK (20)
WHERE url LIKE '/docs/%';

55. Стабильная доля по ключу (альтернатива)

SELECT *
FROM orders
WHERE MOD(ORA_HASH(customer_id), 100) < 5;

56. Сравнение двух долей подвыборки

SELECT 'small' AS tag, COUNT(*) AS n FROM orders SAMPLE (4)
UNION ALL
SELECT 'big'   AS tag, COUNT(*) AS n FROM orders SAMPLE (10);

57. Выборка и WINDOW‑аналитика

SELECT
  customer_id,
  SUM(amount) OVER (PARTITION BY customer_id) AS total_by_customer
FROM orders SAMPLE (0.5);

58. Семпл и подмножество колонок

SELECT customer_id, created_at, country
FROM customers SAMPLE (4);

59. Проверка гипотезы JOIN‑качества на подвыборке

SELECT COUNT(*) AS matches
FROM orders SAMPLE (20) o
JOIN shipments s ON s.order_id = o.order_id;

60. Бенчмарк — сравнить планы на подвыборке

EXPLAIN PLAN FOR
SELECT /* test */ * FROM big_table SAMPLE (8);
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

Еще 20 примеров.

61. Блочное семплирование 20% с SEED

SELECT *
FROM app_logs SAMPLE BLOCK (25) SEED (77);

62. Фиксированная подвыборка для отчёта дня

SELECT *
FROM transactions SAMPLE (10) SEED (TO_NUMBER(TO_CHAR(SYSDATE,'J')));

63. Подвыборка и HAVING по сумме

SELECT product_id, SUM(amount) AS total
FROM sales SAMPLE (3)
GROUP BY product_id
HAVING SUM(amount) > 1000;

64. Семпл в правой таблице JOIN

SELECT e.emp_id, d.dept_name
FROM employees e
JOIN departments SAMPLE (12) d ON d.dept_id = e.dept_id;

65. Семпл с типичным WHERE‑фильтром

SELECT *
FROM sessions SAMPLE (6)
WHERE device = 'mobile' AND country = 'DE';

66. Вложенный UNION ALL c семплом в каждом плече

SELECT 'A' src, COUNT(*) n FROM a SAMPLE (7)
UNION ALL
SELECT 'B' src, COUNT(*) n FROM b SAMPLE (8);

67. Подвыборка для визуализации временного ряда

SELECT ts, metric
FROM metrics SAMPLE (12)
WHERE ts >= SYSTIMESTAMP - INTERVAL '7' DAY;

68. Сэмпл и вычисляемые поля

SELECT order_id, amount, amount*0.2 AS vat
FROM orders SAMPLE (1);

69. Блочный режим для больших архивов

SELECT *
FROM archive_audit SAMPLE BLOCK (12);

70. Разные SEED для сравнения стабильности

SELECT COUNT(*) n FROM t SAMPLE (10) SEED (1);
SELECT COUNT(*) m FROM t SAMPLE (12) SEED (2);

71. Подвыборка и оконная медиана

SELECT
  PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS p50
FROM orders SAMPLE (6);

72. Семпл перед материализацией во временную таблицу

CREATE GLOBAL TEMPORARY TABLE tmp_orders AS
SELECT * FROM orders SAMPLE (7);

73. Сэмпл и удаление дубликатов

SELECT DISTINCT customer_id
FROM orders SAMPLE (1);

74. Фиксируем дневной SEED от даты

SELECT *
FROM big_table SAMPLE (3) SEED (TO_NUMBER(TO_CHAR(CURRENT_DATE,'DDD')));

75. Подвыборка с сортировкой по времени

SELECT *
FROM events SAMPLE (2)
ORDER BY event_ts DESC;

76. Семпл в подзапросе внутри WHERE IN

SELECT *
FROM customers
WHERE customer_id IN (
  SELECT customer_id
  FROM orders SAMPLE (1)
);

77. Подвыборка для быстрой валидации схемы

SELECT table_name, column_name, data_type
FROM user_tab_columns SAMPLE (7);

78. Блочный режим на партиции за месяц

SELECT *
FROM sales_2025_01 SAMPLE BLOCK (10);

79. Сэмпл и вычисление DISTINCT‑количества

SELECT COUNT(DISTINCT customer_id) AS dc
FROM orders SAMPLE (3);

80. Прототип отчёта: топ‑категории на подвыборке

SELECT category, SUM(amount) AS total
FROM sales SAMPLE (4)
GROUP BY category
ORDER BY total DESC
FETCH FIRST 10 ROWS ONLY;

Еще 20 примеров.

81. Базовая случайная подвыборка 1%

SELECT *
FROM customers SAMPLE (6);

82. Блочное семплирование 10% для логов

SELECT *
FROM app_logs SAMPLE BLOCK (10);

83. Фиксируем результат через SEED(42)

SELECT *
FROM transactions SAMPLE (8) SEED (42);

84. Семпл и фильтр в WHERE

SELECT order_id, amount
FROM orders SAMPLE (3)
WHERE status = 'PAID';

85. Подвыборка и агрегаты в GROUP BY

SELECT country, COUNT(*) AS cnt
FROM customers SAMPLE (5)
GROUP BY country;

86. Семпл в JOIN: семплируем только левую таблицу

SELECT o.order_id, c.customer_name
FROM orders SAMPLE (1) o
JOIN customers c ON c.customer_id = o.customer_id;

87. Семпл в JOIN обеих таблиц

SELECT o.order_id, c.segment
FROM orders SAMPLE (8) o
JOIN customers SAMPLE (6) c ON c.customer_id = o.customer_id;

88. Подвыборка с ORDER BY и ограничением результата

SELECT *
FROM products SAMPLE (7)
ORDER BY created_at
FETCH FIRST 100 ROWS ONLY;

89. Блочное семплирование на партиционированной таблице

SELECT *
FROM sales_part SAMPLE BLOCK (8)
WHERE sales_date >= DATE '2025-01-01';

90. Репликация результата: одинаковый SEED

SELECT COUNT(*) AS n1
FROM events SAMPLE (8) SEED (100);
-- Перезапуск с тем же SEED даст ту же мощность выборки (при неизменных данных)

91. Вложенный подзапрос: семплируем подтаблицу

SELECT product_id, SUM(amount) AS total
FROM (
  SELECT product_id, amount
  FROM sales SAMPLE (2)
) s
GROUP BY product_id;

92. Семпл и DISTINCT

SELECT DISTINCT country
FROM customers SAMPLE (2);

93. Оценка среднего чека по подвыборке

SELECT AVG(amount) AS avg_check
FROM orders SAMPLE (12);

94. Семпл по большим таблицам — блочный режим

SELECT *
FROM pageviews SAMPLE BLOCK (10)
WHERE url LIKE '/docs/%';

95. Стабильная доля по ключу (альтернатива)

SELECT *
FROM orders
WHERE MOD(ORA_HASH(customer_id), 100) < 5;

96. Сравнение двух долей подвыборки

SELECT 'small' AS tag, COUNT(*) AS n FROM orders SAMPLE (1)
UNION ALL
SELECT 'big'   AS tag, COUNT(*) AS n FROM orders SAMPLE (0.5);

97. Выборка и WINDOW‑аналитика

SELECT
  customer_id,
  SUM(amount) OVER (PARTITION BY customer_id) AS total_by_customer
FROM orders SAMPLE (5);

98. Семпл и подмножество колонок

SELECT customer_id, created_at, country
FROM customers SAMPLE (10);

99. Проверка гипотезы JOIN‑качества на подвыборке

SELECT COUNT(*) AS matches
FROM orders SAMPLE (10) o
JOIN shipments s ON s.order_id = o.order_id;

100. Бенчмарк — сравнить планы на подвыборке

EXPLAIN PLAN FOR
SELECT /* test */ * FROM big_table SAMPLE (6);
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

Частые ошибки и подводные камни

  1. Непостоянство без SEED. Каждый запуск без SEED даёт иную подвыборку.
  2. Переоценка равномерности. BLOCK может смещать доли по регионам/датам, если данные кластеризованы.
  3. Малые проценты. При 0.1% на маленьких таблицах можно получить 0 строк.
  4. Индексные доступы. Семплирование относится к таблице; индексы не «семплируются».
  5. JOIN‑эффект. Семплирование каждой таблицы независимо: перехлёст по ключам случаен.

Альтернативы

  • Псевдослучайный фильтр: WHERE MOD(ORA_HASH(key), 100) < 5 — стабильная доля по ключу.
  • Генератор: WHERE DBMS_RANDOM.VALUE < 0.05 — строковое семплирование без BLOCK.
  • Материализация подвыборки во временную таблицу для повторного использования.

Заключение

SAMPLE помогает быстро смотреть на большие таблицы и строить прототипы без долгих сканов.
Используйте SEED для воспроизводимости, а при кластеризованных данных сравните результаты с хэш‑фильтрами по ключу.

Документация

Oracle SQL Reference — SELECT (табличное семплирование)


🔜 Следующая статья:

KEEP в Oracle SQL — как выбрать максимум или минимум


Понравилась статья? Поделиться с друзьями: