توضح لك هذه المقالة كيفية استخدام تسريع الاستعلام لاسترداد مجموعة فرعية من البيانات من حساب التخزين الخاص بك.
يتيح تسريع الاستعلام للتطبيقات وأطر عمل التحليلات تحسين معالجة البيانات بشكل كبير عن طريق استرداد البيانات التي يحتاجونها فقط لتنفيذ عملية معينة. لمعرفة المزيد، راجع تسريع استعلام Azure Data Lake Storage.
قم بتثبيت الإصدار 4.6.0 من الوحدة النمطية Az أو أعلى.
Install-Module -Name Az -Repository PSGallery -Force
للتحديث من إصدار أقدم من Az، قم بتشغيل الأمر التالي:
Update-Module -Name Az
افتح موجه الأوامر وقم بتغيير الدليل (cd) في مجلد المشروع الخاص بك على سبيل المثال:
cd myProject
قم بتثبيت الإصدار 12.5.0-preview.6 أو إصدار أحدث من مكتبة عميل تخزين Azure Blob لحزمة .NET باستخدام الأمر dotnet add package .
dotnet add package Azure.Storage.Blobs -v 12.8.0
تقوم الأمثلة التي تظهر في هذه المقالة بتحليل ملف CSV باستخدام مكتبة CsvHelper . لاستخدام هذه المكتبة، استخدم الأمر التالي.
dotnet add package CsvHelper
افتح ملفpom.xml لمشروعك في محرر نصوص. أضف عناصر التبعية التالية إلى مجموعة التبعيات.
<!-- Request static dependencies from Maven -->
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-storage-blob</artifactId>
<version>12.8.0-beta.1</version>
</dependency>
قم بتثبيت مكتبة عميل Azure Data Lake Storage ل Python باستخدام نقطة.
pip install azure-storage-blob==12.4.0
قم بتثبيت مكتبة عميل Data Lake ل JavaScript عن طريق فتح نافذة طرفية، ثم كتابة الأمر التالي.
npm install @azure/storage-blob
npm install @fast-csv/parse
أضف هذه using العبارات إلى أعلى ملف التعليمات البرمجية.
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Blobs.Specialized;
يسترد تسريع الاستعلام البيانات المنسقة CSV وJSON. لذلك، تأكد من إضافة عبارات استخدام لأي مكتبات تحليل CSV أو JSON تختار استخدامها. تقوم الأمثلة التي تظهر في هذه المقالة بتحليل ملف CSV باستخدام مكتبة CsvHelper المتوفرة على NuGet. لذلك ، سنضيف هذه using العبارات إلى أعلى ملف التعليمات البرمجية.
using CsvHelper;
using CsvHelper.Configuration;
لتجميع الأمثلة المعروضة في هذه المقالة ، ستحتاج أيضا إلى إضافة هذه using العبارات أيضا.
using System.Threading.Tasks;
using System.IO;
using System.Globalization;
أضف هذه import العبارات إلى أعلى ملف التعليمات البرمجية.
import com.azure.storage.blob.*;
import com.azure.storage.blob.options.*;
import com.azure.storage.blob.models.*;
import com.azure.storage.common.*;
import java.io.*;
import java.util.function.Consumer;
import org.apache.commons.csv.*;
أضف عبارات الاستيراد هذه إلى أعلى ملف التعليمات البرمجية.
import sys, csv
from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient, DelimitedTextDialect, BlobQueryError
قم بتضمين الوحدة storage-blob النمطية عن طريق وضع هذه العبارة في أعلى ملف التعليمات البرمجية الخاص بك.
const { BlobServiceClient } = require("@azure/storage-blob");
يسترد تسريع الاستعلام البيانات المنسقة CSV وJSON. لذلك، تأكد من إضافة عبارات لأي وحدات تحليل CSV أو JSON تختار استخدامها. تقوم الأمثلة التي تظهر في هذه المقالة بتحليل ملف CSV باستخدام الوحدة النمطية fast-csv . لذلك ، سنضيف هذه العبارة إلى أعلى ملف التعليمات البرمجية.
const csv = require('@fast-csv/parse');
يمكنك استخدام SQL لتحديد مسندات تصفية الصفوف وإسقاطات الأعمدة في طلب تسريع الاستعلام. تستعلم التعليمات البرمجية التالية عن ملف CSV في التخزين وترجع جميع صفوف البيانات حيث يطابق العمود الثالث القيمة Hemingway, Ernest.
Function Get-QueryCsv($ctx, $container, $blob, $query, $hasheaders) {
$tempfile = New-TemporaryFile
$informat = New-AzStorageBlobQueryConfig -AsCsv -HasHeader:$hasheaders -RecordSeparator "`n" -ColumnSeparator "," -QuotationCharacter """" -EscapeCharacter "\"
Get-AzStorageBlobQueryResult -Context $ctx -Container $container -Blob $blob -InputTextConfiguration $informat -OutputTextConfiguration (New-AzStorageBlobQueryConfig -AsCsv -HasHeader -RecordSeparator "`n" -ColumnSeparator "," -QuotationCharacter """" -EscapeCharacter "\") -ResultFile $tempfile.FullName -QueryString $query -Force
Get-Content $tempfile.FullName
}
$container = "data"
$blob = "csv/csv-general/seattle-library.csv"
Get-QueryCsv $ctx $container $blob "SELECT * FROM BlobStorage WHERE _3 = 'Hemingway, Ernest, 1899-1961'" $false
يرسل الأسلوب BlockBlobClient.QueryAsync غير المتزامن الاستعلام إلى واجهة برمجة تطبيقات تسريع الاستعلام، ثم يدفق النتائج مرة أخرى إلى التطبيق ككائن دفق .
static async Task QueryHemingway(BlockBlobClient blob)
{
string query = @"SELECT * FROM BlobStorage WHERE _3 = 'Hemingway, Ernest, 1899-1961'";
await DumpQueryCsv(blob, query, false);
}
private static async Task DumpQueryCsv(BlockBlobClient blob, string query, bool headers)
{
try
{
var options = new BlobQueryOptions()
{
InputTextConfiguration = new BlobQueryCsvTextOptions()
{
HasHeaders = true,
RecordSeparator = "\n",
ColumnSeparator = ",",
EscapeCharacter = '\\',
QuotationCharacter = '"'
},
OutputTextConfiguration = new BlobQueryCsvTextOptions()
{
HasHeaders = true,
RecordSeparator = "\n",
ColumnSeparator = ",",
EscapeCharacter = '\\',
QuotationCharacter = '"' },
ProgressHandler = new Progress<long>((finishedBytes) =>
Console.Error.WriteLine($"Data read: {finishedBytes}"))
};
options.ErrorHandler += (BlobQueryError err) => {
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine($"Error: {err.Position}:{err.Name}:{err.Description}");
Console.ResetColor();
};
// BlobDownloadInfo exposes a Stream that will make results available when received rather than blocking for the entire response.
using (var reader = new StreamReader((await blob.QueryAsync(
query,
options)).Value.Content))
{
using (var parser = new CsvReader
(reader, new CsvConfiguration(CultureInfo.CurrentCulture) { HasHeaderRecord = true }))
{
while (await parser.ReadAsync())
{
Console.Out.WriteLine(String.Join(" ", parser.Parser.Record));
}
}
}
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Exception: " + ex.ToString());
}
}
ترسل الطريقة BlockBlobClient.openInputStream() الاستعلام إلى واجهة برمجة تطبيقات تسريع الاستعلام، ثم تقوم ببث النتائج مرة أخرى إلى التطبيق ككائن InputStream يمكن قراءته مثل أي كائن InputStream آخر.
static void QueryHemingway(BlobClient blobClient) {
String expression = "SELECT * FROM BlobStorage WHERE _3 = 'Hemingway, Ernest, 1899-1961'";
DumpQueryCsv(blobClient, expression, true);
}
static void DumpQueryCsv(BlobClient blobClient, String query, Boolean headers) {
try {
BlobQuerySerialization input = new BlobQueryDelimitedSerialization()
.setRecordSeparator('\n')
.setColumnSeparator(',')
.setHeadersPresent(headers)
.setFieldQuote('\0')
.setEscapeChar('\\');
BlobQuerySerialization output = new BlobQueryDelimitedSerialization()
.setRecordSeparator('\n')
.setColumnSeparator(',')
.setHeadersPresent(true)
.setFieldQuote('\0')
.setEscapeChar('\n');
Consumer<BlobQueryError> errorConsumer = System.out::println;
Consumer<BlobQueryProgress> progressConsumer = progress -> System.out.println("total bytes read: " + progress.getBytesScanned());
BlobQueryOptions queryOptions = new BlobQueryOptions(query)
.setInputSerialization(input)
.setOutputSerialization(output)
.setErrorConsumer(errorConsumer)
.setProgressConsumer(progressConsumer);
/* Open the query input stream. */
InputStream stream = blobClient.openQueryInputStream(queryOptions).getValue();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
/* Read from stream like you normally would. */
for (CSVRecord record : CSVParser.parse(reader, CSVFormat.EXCEL.withHeader())) {
System.out.println(record.toString());
}
}
} catch (Exception e) {
System.err.println("Exception: " + e.toString());
e.printStackTrace(System.err);
}
}
def query_hemingway(blob: BlobClient):
query = "SELECT * FROM BlobStorage WHERE _3 = 'Hemingway, Ernest, 1899-1961'"
dump_query_csv(blob, query, False)
def dump_query_csv(blob: BlobClient, query: str, headers: bool):
qa_reader = blob.query_blob(query, blob_format=DelimitedTextDialect(has_header=headers), on_error=report_error, encoding='utf-8')
# records() returns a generator that will stream results as received. It will not block pending all results.
csv_reader = csv.reader(qa_reader.records())
for row in csv_reader:
print("*".join(row))
يرسل هذا المثال الاستعلام إلى واجهة برمجة تطبيقات تسريع الاستعلام، ثم يقوم ببث النتائج مرة أخرى. الكائن الذي blob تم تمريره إلى queryHemingway الدالة المساعدة هو من النوع BlockBlobClient. لمعرفة المزيد حول كيفية الحصول على كائن BlockBlobClient ، راجع التشغيل السريع: إدارة الكائنات الثنائية كبيرة الحجم باستخدام JavaScript v12 SDK في Node.js.
async function queryHemingway(blob)
{
const query = "SELECT * FROM BlobStorage WHERE _3 = 'Hemingway, Ernest, 1899-1961'";
await dumpQueryCsv(blob, query, false);
}
async function dumpQueryCsv(blob, query, headers)
{
var response = await blob.query(query, {
inputTextConfiguration: {
kind: "csv",
recordSeparator: '\n',
hasHeaders: headers
},
outputTextConfiguration: {
kind: "csv",
recordSeparator: '\n',
hasHeaders: true
},
onProgress: (progress) => console.log(`Data read: ${progress.loadedBytes}`),
onError: (err) => console.error(`Error: ${err.position}:${err.name}:${err.description}`)});
return new Promise(
function (resolve, reject) {
csv.parseStream(response.readableStreamBody)
.on('data', row => console.log(row))
.on('error', error => {
console.error(error);
reject(error);
})
.on('end', rowCount => resolve());
});
}
يمكنك تحديد نطاق نتائجك إلى مجموعة فرعية من الأعمدة. بهذه الطريقة يمكنك استرداد الأعمدة المطلوبة فقط لإجراء عملية حسابية معينة. يؤدي ذلك إلى تحسين أداء التطبيق وتقليل التكلفة لأنه يتم نقل بيانات أقل عبر الشبكة.
Function Get-QueryCsv($ctx, $container, $blob, $query, $hasheaders) {
$tempfile = New-TemporaryFile
$informat = New-AzStorageBlobQueryConfig -AsCsv -HasHeader:$hasheaders
Get-AzStorageBlobQueryResult -Context $ctx -Container $container -Blob $blob -InputTextConfiguration $informat -OutputTextConfiguration (New-AzStorageBlobQueryConfig -AsCsv -HasHeader) -ResultFile $tempfile.FullName -QueryString $query -Force
Get-Content $tempfile.FullName
}
$container = "data"
$blob = "csv/csv-general/seattle-library-with-headers.csv"
Get-QueryCsv $ctx $container $blob "SELECT BibNum FROM BlobStorage" $true
static async Task QueryBibNum(BlockBlobClient blob)
{
string query = @"SELECT BibNum FROM BlobStorage";
await DumpQueryCsv(blob, query, true);
}
static void QueryBibNum(BlobClient blobClient)
{
String expression = "SELECT BibNum FROM BlobStorage";
DumpQueryCsv(blobClient, expression, true);
}
def query_bibnum(blob: BlobClient):
query = "SELECT BibNum FROM BlobStorage"
dump_query_csv(blob, query, True)
async function queryBibNum(blob)
{
const query = "SELECT BibNum FROM BlobStorage";
await dumpQueryCsv(blob, query, true);
}
تجمع التعليمات البرمجية التالية بين تصفية الصفوف وإسقاطات الأعمدة في نفس الاستعلام.
Get-QueryCsv $ctx $container $blob $query $true
Function Get-QueryCsv($ctx, $container, $blob, $query, $hasheaders) {
$tempfile = New-TemporaryFile
$informat = New-AzStorageBlobQueryConfig -AsCsv -HasHeader:$hasheaders
Get-AzStorageBlobQueryResult -Context $ctx -Container $container -Blob $blob -InputTextConfiguration $informat -OutputTextConfiguration (New-AzStorageBlobQueryConfig -AsCsv -HasHeader) -ResultFile $tempfile.FullName -QueryString $query -Force
Get-Content $tempfile.FullName
}
$container = "data"
$query = "SELECT BibNum, Title, Author, ISBN, Publisher, ItemType
FROM BlobStorage
WHERE ItemType IN
('acdvd', 'cadvd', 'cadvdnf', 'calndvd', 'ccdvd', 'ccdvdnf', 'jcdvd', 'nadvd', 'nadvdnf', 'nalndvd', 'ncdvd', 'ncdvdnf')"
static async Task QueryDvds(BlockBlobClient blob)
{
string query = @"SELECT BibNum, Title, Author, ISBN, Publisher, ItemType
FROM BlobStorage
WHERE ItemType IN
('acdvd', 'cadvd', 'cadvdnf', 'calndvd', 'ccdvd', 'ccdvdnf', 'jcdvd', 'nadvd', 'nadvdnf', 'nalndvd', 'ncdvd', 'ncdvdnf')";
await DumpQueryCsv(blob, query, true);
}
static void QueryDvds(BlobClient blobClient)
{
String expression = "SELECT BibNum, Title, Author, ISBN, Publisher, ItemType " +
"FROM BlobStorage " +
"WHERE ItemType IN " +
" ('acdvd', 'cadvd', 'cadvdnf', 'calndvd', 'ccdvd', 'ccdvdnf', 'jcdvd', 'nadvd', 'nadvdnf', 'nalndvd', 'ncdvd', 'ncdvdnf')";
DumpQueryCsv(blobClient, expression, true);
}
def query_dvds(blob: BlobClient):
query = "SELECT BibNum, Title, Author, ISBN, Publisher, ItemType "\
"FROM BlobStorage "\
"WHERE ItemType IN "\
" ('acdvd', 'cadvd', 'cadvdnf', 'calndvd', 'ccdvd', 'ccdvdnf', 'jcdvd', 'nadvd', 'nadvdnf', 'nalndvd', 'ncdvd', 'ncdvdnf')"
dump_query_csv(blob, query, True)
async function queryDvds(blob)
{
const query = "SELECT BibNum, Title, Author, ISBN, Publisher, ItemType " +
"FROM BlobStorage " +
"WHERE ItemType IN " +
" ('acdvd', 'cadvd', 'cadvdnf', 'calndvd', 'ccdvd', 'ccdvdnf', 'jcdvd', 'nadvd', 'nadvdnf', 'nalndvd', 'ncdvd', 'ncdvdnf')";
await dumpQueryCsv(blob, query, true);
}