الانتقال إلى المحتوى الرئيسي
يوفّر واجهة شبيهة بالجداول للاستعلام عن الملفات وإدراجها في Amazon S3 وGoogle Cloud Storage. تشبه دالة الجدول هذه دالة hdfs، لكنها توفّر ميزات خاصة بـ S3. إذا كان لديك عدة نسخ متماثلة في عنقودك، فيمكنك استخدام دالة s3Cluster بدلًا من ذلك لموازاة عمليات الإدراج. عند استخدام s3 table function مع INSERT INTO...SELECT، تُقرأ البيانات وتُدرج بأسلوب تدفقي. ولا يبقى في الذاكرة إلا عدد قليل من كتل البيانات، بينما تُقرأ الكتل باستمرار من S3 وتُرسَل إلى الجدول الوجهة.

الصيغة

s3(url [, NOSIGN | access_key_id, secret_access_key, [session_token]] [,format] [,structure] [,compression_method],[,headers], [,extra_credentials], [,partition_strategy], [,partition_columns_in_data_file])
s3(named_collection[, option=value [,..]])
GCSتتكامل دالة الجدول S3 مع Google Cloud Storage باستخدام GCS XML API ومفاتيح HMAC. راجع مستندات التوافق من Google لمزيد من التفاصيل حول نقطة النهاية وHMAC.بالنسبة إلى GCS، استبدل HMAC Key وHMAC secret الخاصين بك في الموضعين اللذين يظهر فيهما access_key_id وsecret_access_key.
المعلمات تدعم دالة الجدول s3 المعلمات البسيطة التالية:
ParameterDescription
urlURL حاوية التخزين مع المسار إلى الملف. يدعم أحرف البدل التالية في وضع readonly: * و** و? و{abc,def} و{N..M}، حيث إن N وM رقمان، و'abc' و'def' سلسلتان نصيتان. لمزيد من المعلومات، راجع هنا.
NOSIGNإذا جرى تمرير هذه الكلمة المفتاحية بدلًا من بيانات الاعتماد، فلن تُوقَّع أي من الطلبات.
access_key_id and secret_access_keyمفاتيح تحدد بيانات الاعتماد المطلوب استخدامها مع نقطة النهاية المحددة. اختيارية.
session_tokenرمز جلسة لاستخدامه مع المفاتيح المحددة. وهو اختياري عند تمرير المفاتيح.
formatالتنسيق الخاص بالملف.
structureبنية الجدول. بالتنسيق 'column1_name column1_type, column2_name column2_type, ...'.
compression_methodهذه المعلمة اختيارية. القيم المدعومة: none وgzip أو gz وbrotli أو br وxz أو LZMA وzstd أو zst. افتراضيًا، سيُكتشَف أسلوب الضغط تلقائيًا من امتداد الملف.
headersهذه المعلمة اختيارية. تتيح تمرير الترويسات في طلب S3. مرّرها بالتنسيق headers(key=value)، مثل headers('x-amz-request-payer' = 'requester').
partition_strategyهذه المعلمة اختيارية. القيم المدعومة: wildcard أو hive. تتطلب wildcard وجود {_partition_id} في المسار، ويُستبدل بمفتاح التقسيم. أما hive فلا تسمح بأحرف البدل، وتفترض أن المسار هو جذر الجدول، وتُنشئ أدلة partition بنمط Hive مع Snowflake IDs كأسماء ملفات وتنسيق الملف كامتداد. القيمة الافتراضية هي الإعداد file_like_engine_default_partition_strategy (wildcard ضمن إعدادات compatibility الأقدم من 26.6، وhive بخلاف ذلك).
partition_columns_in_data_fileهذه المعلمة اختيارية. تُستخدم فقط مع استراتيجية التقسيم من نوع hive. وتُخبر ClickHouse ما إذا كان ينبغي توقّع كتابة أعمدة partition داخل ملف البيانات. والقيمة الافتراضية هي false.
extra_credentialsهذه المعلمة اختيارية. تُستخدم لتمرير role_arn من أجل role-based access في ClickHouse Cloud. راجع Secure S3 للاطلاع على خطوات الإعداد.
storage_class_nameهذه المعلمة اختيارية. القيم المدعومة: STANDARD أو INTELLIGENT_TIERING. وتتيح تحديد AWS S3 Intelligent Tiering. والقيمة الافتراضية هي STANDARD.
GCSيكون URL الخاص بـ GCS بهذا التنسيق لأن نقطة النهاية الخاصة بـ Google XML API تختلف عن JSON API:
  https://storage.googleapis.com/<bucket>/<folder>/<filename(s)>
وليس https://storage.cloud.google.com.
يمكن أيضًا تمرير الوسيطات باستخدام named collections. في هذه الحالة، تعمل url وaccess_key_id وsecret_access_key وformat وstructure وcompression_method بالطريقة نفسها، كما تتوفر بعض المعلمات الإضافية المدعومة:
الوسيطةالوصف
filenameيُلحَق بـ URL إذا جرى تحديده.
use_environment_credentialsمُفعَّل افتراضيًا، ويتيح تمرير معلمات إضافية باستخدام متغيرات البيئة AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_EC2_METADATA_DISABLED.
no_sign_requestمُعطَّل افتراضيًا.
expiration_window_secondsالقيمة الافتراضية هي 120.

القيمة المعادة

جدول ذو البنية المحددة لقراءة البيانات أو كتابتها في الملف المحدد.

أمثلة

تحديد أول 5 صفوف من الجدول من ملف S3 ‏https://datasets-documentation.s3.eu-west-3.amazonaws.com/aapl_stock.csv:
SELECT *
FROM s3(
   'https://datasets-documentation.s3.eu-west-3.amazonaws.com/aapl_stock.csv',
   'CSVWithNames'
)
LIMIT 5;
┌───────Date─┬────Open─┬────High─┬─────Low─┬───Close─┬───Volume─┬─OpenInt─┐
│ 1984-09-07 │ 0.42388 │ 0.42902 │ 0.41874 │ 0.42388 │ 23220030 │       0 │
│ 1984-09-10 │ 0.42388 │ 0.42516 │ 0.41366 │ 0.42134 │ 18022532 │       0 │
│ 1984-09-11 │ 0.42516 │ 0.43668 │ 0.42516 │ 0.42902 │ 42498199 │       0 │
│ 1984-09-12 │ 0.42902 │ 0.43157 │ 0.41618 │ 0.41618 │ 37125801 │       0 │
│ 1984-09-13 │ 0.43927 │ 0.44052 │ 0.43927 │ 0.43927 │ 57822062 │       0 │
└────────────┴─────────┴─────────┴─────────┴─────────┴──────────┴─────────┘
يستخدم ClickHouse امتدادات أسماء الملفات لتحديد تنسيق البيانات. على سبيل المثال، كان بإمكاننا تشغيل الأمر السابق من دون CSVWithNames:
SELECT *
FROM s3(
   'https://datasets-documentation.s3.eu-west-3.amazonaws.com/aapl_stock.csv'
)
LIMIT 5;
ويمكن لـ ClickHouse أيضًا تحديد طريقة ضغط الملف. على سبيل المثال، إذا كان الملف مضغوطًا بامتداد .csv.gz، فسيقوم ClickHouse بفك ضغطه تلقائيًا.
قد تُربك ملفات Parquet ذات الأسماء مثل *.parquet.snappy أو *.parquet.zstd ClickHouse، وتتسبب في ظهور الخطأين TOO_LARGE_COMPRESSED_BLOCK أو ZSTD_DECODER_FAILED. ويحدث ذلك لأن ClickHouse سيحاول قراءة الملف بالكامل على أنه بيانات مرمّزة باستخدام Snappy أو ZSTD، بينما يطبّق Parquet الضغط على مستوى مجموعات الصفوف والأعمدة.تحدد البيانات الوصفية في Parquet الضغط لكل عمود بالفعل، لذا يكون امتداد الملف زائدًا عن الحاجة. يمكنك ببساطة استخدام compression_method = 'none' في مثل هذه الحالات:
SELECT *
FROM s3(
  'https://<my-bucket>.s3.<my-region>.amazonaws.com/path/to/my-data.parquet.snappy',
  compression_format = 'none'
);

الاستخدام

لنفترض أن لدينا عدة ملفات بعناوين URI التالية على S3: احسب عدد الصفوف في الملفات التي تنتهي بأرقام من 1 إلى 3:
SELECT count(*)
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32')
┌─count()─┐
│      18 │
└─────────┘
احسب العدد الإجمالي للصفوف في جميع الملفات الموجودة في هذين الدليلين:
SELECT count(*)
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/my-test-bucket-768/{some,another}_prefix/*', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32')
┌─count()─┐
│      24 │
└─────────┘
إذا كانت قائمة ملفاتك تتضمن نطاقات رقمية تبدأ بأصفار بادئة، فاستخدم الصيغة التي تحتوي على أقواس لكل رقم على حدة، أو استخدم ?.
احسب العدد الإجمالي للصفوف في الملفات المسماة file-000.csv، file-001.csv، … ، file-999.csv:
SELECT count(*)
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/my-test-bucket-768/big_prefix/file-{000..999}.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32');
┌─count()─┐
│      12 │
└─────────┘
أدرج البيانات في الملف test-data.csv.gz:
INSERT INTO FUNCTION s3('https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/test-data.csv.gz', 'CSV', 'name String, value UInt32', 'gzip')
VALUES ('test-data', 1), ('test-data-2', 2);
أدرج البيانات في الملف test-data.csv.gz من جدول موجود:
INSERT INTO FUNCTION s3('https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/test-data.csv.gz', 'CSV', 'name String, value UInt32', 'gzip')
SELECT name, value FROM existing_table;
يمكن استخدام ** في Glob للاجتياز التعاودي للمجلدات. انظر المثال أدناه، إذ سيجلب جميع الملفات من مجلد my-test-bucket-768 بشكل تعاودي:
SELECT * FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/**', 'CSV', 'name String, value UInt32', 'gzip');
يجلب ما يلي البيانات من جميع ملفات test-data.csv.gz الموجودة في أي مجلد داخل دليل my-test-bucket بشكل تعاودي:
SELECT * FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/**/test-data.csv.gz', 'CSV', 'name String, value UInt32', 'gzip');
ملاحظة. يمكن تحديد محوّلات URL مخصصة في ملف تكوين الخادم. مثال:
SELECT * FROM s3('s3://clickhouse-public-datasets/my-test-bucket-768/**/test-data.csv.gz', 'CSV', 'name String, value UInt32', 'gzip');
سيتم استبدال URL 's3://clickhouse-public-datasets/my-test-bucket-768/**/test-data.csv.gz' بـ 'http://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/**/test-data.csv.gz' يمكن إضافة mapper مخصّص إلى config.xml:
<url_scheme_mappers>
   <s3>
      <to>https://{bucket}.s3.amazonaws.com</to>
   </s3>
   <gs>
      <to>https://{bucket}.storage.googleapis.com</to>
   </gs>
   <oss>
      <to>https://{bucket}.oss.aliyuncs.com</to>
   </oss>
</url_scheme_mappers>
في حالات الاستخدام في بيئة الإنتاج، يُوصى باستخدام named collections. وفيما يلي مثال على ذلك:

CREATE NAMED COLLECTION creds AS
        access_key_id = '***',
        secret_access_key = '***';
SELECT count(*)
FROM s3(creds, url='https://s3-object-url.csv')

الكتابة المُقسَّمة إلى أجزاء

استراتيجية التقسيم

مدعومة فقط لاستعلامات INSERT. wildcard: يستبدل حرف البدل {_partition_id} في مسار الملف بمفتاح التقسيم الفعلي. يُحدَّد افتراضيًا فقط ضمن إعدادات compatibility الأقدم من 26.6؛ وإلا تكون القيمة الافتراضية هي hive (راجع الإعداد file_like_engine_default_partition_strategy). hive يطبّق التقسيم بنمط Hive على عمليات القراءة والكتابة. ويُنشئ الملفات باستخدام التنسيق التالي: <prefix>/<key1=val1/key2=val2...>/<snowflakeid>.<toLower(file_format)>. مثال على استراتيجية التقسيم hive
INSERT INTO FUNCTION s3(s3_conn, filename='t_03363_function', format=Parquet, partition_strategy='hive') PARTITION BY (year, country) SELECT 2020 as year, 'Russia' as country, 1 as id;
SELECT _path, * FROM s3(s3_conn, filename='t_03363_function/**.parquet');

   ┌─_path──────────────────────────────────────────────────────────────────────┬─id─┬─country─┬─year─┐
1. │ test/t_03363_function/year=2020/country=Russia/7351295896279887872.parquet │  1 │ Russia  │ 2020 │
   └────────────────────────────────────────────────────────────────────────────┴────┴─────────┴──────┘
أمثلة على استراتيجية التقسيم wildcard
  1. يؤدي استخدام معرّف القسم في المفتاح إلى إنشاء ملفات منفصلة:
INSERT INTO TABLE FUNCTION
    s3('http://bucket.amazonaws.com/my_bucket/file_{_partition_id}.csv', 'CSV', 'a String, b UInt32, c UInt32')
    PARTITION BY a VALUES ('x', 2, 3), ('x', 4, 5), ('y', 11, 12), ('y', 13, 14), ('z', 21, 22), ('z', 23, 24);
ونتيجةً لذلك، تُكتَب البيانات في ثلاثة ملفات: file_x.csv وfile_y.csv وfile_z.csv.
  1. يؤدّي استخدام معرّف القسم ضمن اسم حاوية التخزين إلى إنشاء ملفات في حاويات تخزين مختلفة:
INSERT INTO TABLE FUNCTION
    s3('http://bucket.amazonaws.com/my_bucket_{_partition_id}/file.csv', 'CSV', 'a UInt32, b UInt32, c UInt32')
    PARTITION BY a VALUES (1, 2, 3), (1, 4, 5), (10, 11, 12), (10, 13, 14), (20, 21, 22), (20, 23, 24);
ونتيجةً لذلك، تُكتب البيانات في ثلاثة ملفات ضمن حاويات تخزين مختلفة: my_bucket_1/file.csv وmy_bucket_10/file.csv وmy_bucket_20/file.csv.

الوصول إلى حاويات التخزين العامة

يحاول ClickHouse جلب بيانات الاعتماد من أنواع متعددة من المصادر. وقد يؤدي ذلك أحيانًا إلى حدوث مشكلات عند الوصول إلى بعض حاويات التخزين العامة، ما يتسبب في أن يعيد العميل رمز الخطأ 403. يمكن تجنب هذه المشكلة باستخدام الكلمة المحجوزة NOSIGN، ما يُجبر العميل على تجاهل جميع بيانات الاعتماد وعدم توقيع الطلبات.
SELECT *
FROM s3(
   'https://datasets-documentation.s3.eu-west-3.amazonaws.com/aapl_stock.csv',
   NOSIGN,
   'CSVWithNames'
)
LIMIT 5;

استخدام بيانات اعتماد S3 ‏(ClickHouse Cloud)

بالنسبة إلى حاويات التخزين غير العامة، يمكن للمستخدمين تمرير aws_access_key_id وaws_secret_access_key إلى الدالة. على سبيل المثال:
SELECT count() FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/mta/*.tsv', '<KEY>', '<SECRET>','TSVWithNames')
يُعد هذا مناسبًا لعمليات الوصول لمرة واحدة أو في الحالات التي يمكن فيها تغيير بيانات الاعتماد بسهولة. ومع ذلك، لا يُنصح به كحل طويل الأمد لعمليات الوصول المتكررة أو عندما تكون بيانات الاعتماد حساسة. في هذه الحالة، نوصي بأن يعتمد المستخدمون على الوصول المستند إلى الأدوار. يَرِد توثيق الوصول المستند إلى الأدوار لـ S3 في ClickHouse Cloud هنا. بعد الإعداد، يمكن تمرير roleARN إلى الدالة s3 عبر المعلمة extra_credentials. على سبيل المثال:
SELECT count() FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/mta/*.tsv','CSVWithNames',extra_credentials(role_arn = 'arn:aws:iam::111111111111:role/ClickHouseAccessRole-001'))
يمكن أيضًا تمرير external_id اختياريًا إلى جانب role_arn. ويُمرَّر كمعلمة ExternalId في استدعاء AWS STS AssumeRole، ويتيح لسياسة الثقة الخاصة بالدور أن تشترط سرًا مشتركًا، مما يحدّ من مشكلة النائب المرتبك. على سبيل المثال:
SELECT count() FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/mta/*.tsv','CSVWithNames',extra_credentials(role_arn = 'arn:aws:iam::111111111111:role/ClickHouseAccessRole-001', external_id = 'my-external-id'))
يمكنك العثور على المزيد من الأمثلة هنا

العمل مع الأرشيفات

لنفترض أن لدينا عدة ملفات أرشيف بعناوين URI التالية على S3: يمكن استخراج البيانات من هذه الأرشيفات باستخدام ::. ويمكن استخدام أنماط globs سواء في جزء URL أو في الجزء الذي يلي :: (وهو المسؤول عن اسم الملف داخل الأرشيف).
SELECT *
FROM s3(
   'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m-2018-01-1{0..2}.csv.zip :: *.csv'
);
يدعم ClickHouse ثلاثة تنسيقات للأرشيف: ZIP TAR 7Z وبينما يمكن الوصول إلى أرشيفات ZIP وTAR من أي موقع تخزين مدعوم، فلا يمكن قراءة أرشيفات 7Z إلا من نظام الملفات المحلي الذي ثُبّت عليه ClickHouse.

إدراج البيانات

لاحظ أن الصفوف لا يمكن إدراجها إلا في الملفات الجديدة. ولا توجد دورات دمج أو عمليات تقسيم للملفات. وما إن يُكتَب ملف حتى تفشل عمليات الإدراج اللاحقة. اطّلع على مزيد من التفاصيل هنا.

الأعمدة الافتراضية

  • _path — مسار الملف. النوع: LowCardinality(String). في حالة الأرشيف، يعرض المسار بالتنسيق: "{path_to_archive}::{path_to_file_inside_archive}"
  • _file — اسم الملف. النوع: LowCardinality(String). في حالة الأرشيف، يعرض اسم الملف داخل الأرشيف.
  • _size — حجم الملف بالبايت. النوع: Nullable(UInt64). إذا كان حجم الملف غير معروف، تكون القيمة NULL. في حالة الأرشيف، يعرض حجم الملف غير المضغوط للملف الموجود داخل الأرشيف.
  • _time — وقت آخر تعديل للملف. النوع: Nullable(DateTime). إذا كان الوقت غير معروف، تكون القيمة NULL.

إعداد use_hive_partitioning

هذا تلميح لـ ClickHouse لتحليل الملفات المُقسَّمة بنمط Hive عند القراءة. ولا يؤثر في الكتابة. ولتحقيق تماثل بين القراءة والكتابة، استخدم الوسيطة partition_strategy. عند ضبط use_hive_partitioning على القيمة 1، سيكتشف ClickHouse التقسيم بنمط Hive في المسار (/name=value/) وسيتيح استخدام أعمدة التقسيم بوصفها أعمدة افتراضية في الاستعلام. وستحمل هذه الأعمدة الافتراضية الأسماء نفسها الموجودة في المسار المُقسَّم. مثال
SELECT * FROM s3('s3://data/path/date=*/country=*/code=*/*.parquet') WHERE date > '2020-01-01' AND country = 'Netherlands' AND code = 42;

الوصول إلى حاويات التخزين requester-pays

للوصول إلى حاوية التخزين requester-pays، يجب تمرير الترويسة x-amz-request-payer = requester مع أي طلب. ويتم ذلك بتمرير المعلمة headers('x-amz-request-payer' = 'requester') إلى الدالة s3. على سبيل المثال:
SELECT
    count() AS num_rows,
    uniqExact(_file) AS num_files
FROM s3('https://coiled-datasets-rp.s3.us-east-1.amazonaws.com/1trc/measurements-100*.parquet', 'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', headers('x-amz-request-payer' = 'requester'))

┌───num_rows─┬─num_files─┐
1110000000111
└────────────┴───────────┘

1 row in set. Elapsed: 3.089 sec. Processed 1.09 billion rows, 0.00 B (353.55 million rows/s., 0.00 B/s.)
Peak memory usage: 192.27 KiB.

إعدادات التخزين

  • s3_truncate_on_insert - يتيح تفريغ الملف قبل الإدراج فيه. معطّل افتراضيًا.
  • s3_create_new_file_on_insert - يتيح إنشاء ملف جديد عند كل عملية إدراج إذا كان للتنسيق لاحقة. معطّل افتراضيًا.
  • s3_skip_empty_files - يتيح تخطي الملفات الفارغة أثناء القراءة. مفعّل افتراضيًا.

مخططات Avro المتداخلة

عند قراءة ملفات Avro التي تحتوي على سجلات متداخلة تختلف من ملف إلى آخر (على سبيل المثال، تحتوي بعض الملفات على حقل إضافي داخل كائن متداخل)، فقد يُرجع ClickHouse خطأً مثل:
عدد الأوراق في السجل لا يطابق عدد العناصر في Tuple…
يحدث ذلك لأن ClickHouse يتوقع أن تتطابق جميع بُنى السجلات المتداخلة مع المخطط نفسه. للتعامل مع هذه الحالة، يمكنك:
  • استخدام schema_inference_mode='union' لدمج مخططات السجلات المتداخلة المختلفة، أو
  • مواءمة البُنى المتداخلة يدويًا وتمكين use_structure_from_insertion_table_in_table_functions=1.
ملاحظة حول الأداءقد يستغرق schema_inference_mode='union' وقتًا أطول جدًا مع مجموعات بيانات S3 الكبيرة، لأنه يحتاج إلى فحص كل ملف لاستنتاج المخطط.
مثال
INSERT INTO data_stage
SELECT
    id,
    data
FROM s3('https://bucket-name/*.avro', 'Avro')
SETTINGS schema_inference_mode='union';

## Related           

- [S3 engine](/reference/engines/table-engines/integrations/s3)
- [Integrating S3 with ClickHouse](/integrations/connectors/data-ingestion/AWS/integrating-s3-with-clickhouse)
آخر تعديل في ٢٥ يونيو ٢٠٢٦