Я хочу знать, сколько элементов находится в моей таблице dynamodb. Из руководства API один из способов сделать это – сканирование следующим образом:
<?php $dynamodb = new AmazonDynamoDB(); $scan_response = $dynamodb->scan(array( 'TableName' => 'ProductCatalog' )); echo "Total number of items: ".count($scan_response->body->Items)."\n";
Тем не менее, это должно получить все элементы и сохранить их в массиве в памяти, что не представляется возможным в большинстве случаев, я предполагаю. Есть ли способ получить общее количество предметов более эффективно?
Эти данные недоступны в веб-консоли AWS Dynamo, я уже проверил. (сначала это выглядит так, как показано рядом с кнопками разбиения на страницы, но оказывается, что фигура растет, когда вы переходите на следующую страницу предметов).
Я могу представить три варианта получения общего количества элементов в таблице DynamoDB.
Первый вариант использует сканирование, но функция сканирования неэффективна и, как правило, является плохой практикой, особенно для таблиц с тяжелыми чтениями или производственными таблицами.
Второй вариант – это то, что упоминал Атхарва:
Лучшее решение, которое приходит мне на ум, состоит в том, чтобы поддерживать общее количество подсчетов элементов для таких таблиц в отдельной таблице, где каждый элемент будет иметь имя таблицы как хэш-ключ и общее количество элементов в этой таблице, поскольку это не-ключ атрибут , Затем вы можете сохранить эту таблицу с именем «TotalNumberOfItemsPerTable», обновив ее, сделав операции атомного обновления для увеличения / уменьшения общего количества элементов для конкретной таблицы.
Единственная проблема заключается в том, что операции приращения не являются идемпотентными. Поэтому, если запись терпит неудачу или вы пишете более одного раза, это будет отражено в счете. Если вам нужна точность пин-точки, вместо этого используйте условное обновление.
Простейшим решением является DescribeTable, который возвращает ItemCount. Единственная проблема заключается в том, что счетчик не обновляется. Счет обновляется каждые 6 часов.
http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html
Опция « Count
определенно то, что вы хотите, но вы также должны учитывать, что в результатах сканирования может быть одна или более страниц. Операция «Сканирование» сканирует только 1 МБ данных в вашей таблице, поэтому значение Count
в результате будет отражать только количество первых 1 МБ таблицы. Вам нужно будет сделать последующие запросы, используя значение LastEvaluatedKey
в результате (если оно есть). Вот пример кода для этого:
<?php $dynamo_db = new AmazonDynamoDB(); $total = 0; $start_key = null; $params = array( 'TableName' => 'my-table', 'Count' => true ); do { if ($start_key) { $params['ExclusiveStartKey'] = $start_key->getArrayCopy(); } $response = $dynamo_db->scan($params); if ($response->isOK()) { $total += (string) $response->body->Count; if ($response->body->LastEvaluatedKey) { $start_key = $response->body->LastEvaluatedKey->to_array(); } else { $start_key = null; } } } while ($start_key); echo "Count: {$total}";
Ага, есть опция Count
в API scan
, см. http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#m=AmazonDynamoDB/scan
<?php $dynamodb = new DynamoMetadata(); $scan_response = $dynamodb->scan(array( 'TableName' => 'ProductCatalog' 'Count' => true, )); echo "Count: ".$scan_response->body->Count."\n";
Если вы заинтересованы в использовании общего количества элементов в таблице в логике вашего приложения, это означает, что вы часто будете запрашивать общий счет. Теперь одним из способов достижения этой цели является использование операции сканирования. Но помните, что операция сканирования буквально сканирует всю таблицу и поэтому потребляет большую пропускную способность, поэтому все операции запроса будут получать Throttled Exception в этой длительности. И даже учитывая тот факт, что сканирование ограничит итоговый счет размером 1 МБ, вам придется выполнять повторные операции сканирования, чтобы получить фактическое количество элементов, если таблица очень велика. Для этого потребуется написать пользовательскую логику запроса и обработать неизбежное дросселирование в операциях запроса.
Лучшее решение, которое приходит мне на ум, состоит в том, чтобы поддерживать общее количество подсчетов элементов для таких таблиц в отдельной таблице, где каждый элемент будет иметь имя таблицы как хэш-ключ и общее количество элементов в этой таблице, поскольку это не-ключ атрибут , Затем вы можете сохранить эту таблицу с именем «TotalNumberOfItemsPerTable», обновив ее, сделав операции атомного обновления для увеличения / уменьшения общего количества элементов для конкретной таблицы.
Нет проблем с дросселированием или ограничением 1 МБ.
Кроме того, вы можете расширить эту концепцию до еще большей детализации, например, для поддержания общего количества элементов, соответствующих некоторым хэш-ключам или любым произвольным критериям, которые вы можете кодировать в строковой форме, чтобы сделать запись в вашей таблице с именем «TotalNumberOfItemsInSomeCollection» или «TotalNumberOfItemsInSomeCollection» или « TotalNumberOfItemsMatchingSomeCriteria». Затем эти таблицы могут содержать записи для количества элементов в таблице, для каждой коллекции или элементов, соответствующих некоторым критериям.
Примерное значение счетчика элементов (предположительно обновляемое каждые шесть часов) доступно на консоли AWS для DynamoDB. Просто выберите таблицу и посмотрите под вкладкой «Сведения», последняя запись – «Количество элементов». Если это сработает для вас, то вы можете избежать потребления вашей таблицы пропускной способности, чтобы сделать счет.
Это теперь доступно на экране обзора таблицы AWS в разделе «Данные таблицы», поле «Количество элементов». Кажется, это всего лишь свалка DescribeTable и отмечает, что ее обновление примерно каждые шесть часов.
Вот как я получаю точный счетчик предметов на моем биллинге записей DynamoDB table:
улей>
set dynamodb.throughput.write.percent = 1; set dynamodb.throughput.read.percent = 1; set hive.execution.engine = mr; set mapreduce.reduce.speculative=false; set mapreduce.map.speculative=false; CREATE EXTERNAL TABLE dynamodb_table (`ID` STRING,`DateTime` STRING,`ReportedbyName` STRING,`ReportedbySurName` STRING,`Company` STRING,`Position` STRING,`Country` STRING,`MailDomain` STRING) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES ("dynamodb.table.name" = "BillionData", "dynamodb.column.mapping" = "ID:ID,DateTime:DateTime,ReportedbyName:ReportedbyName,ReportedbySurName:ReportedbySurName,Company:Company,Position:Position,Country:Country,MailDomain:MailDomain"); SELECT count(*) FROM dynamodb_table;
* У вас должен быть кластер EMR, который устанавливается с помощью Hive и DynamoDB Record Handler. * С помощью этой команды обработчик DynamoDB на улье выдает «ПАРАЛЛЕЛЬНЫЕ СКАНИРОВАНИЯ» с несколькими Mapperduce mappers (AKA Workers), работающими на разных разделах, чтобы получить счет. Это будет намного эффективнее и быстрее обычного сканирования.
* Вы должны быть готовы увеличить производительность чтения в течение определенного периода времени. * В приличном размере (20 узлов) кластера, с 10000 RCU, потребовалось 15 минут, чтобы получить счет на миллиард записей Приблиз.
* Новые записи в этой таблице DDB в течение этого периода сделают счет непоследовательным.