your programing

수십억 개의 행을위한 최고의 데이터 저장소

lovepro 2020. 10. 5. 20:33
반응형

수십억 개의 행을위한 최고의 데이터 저장소


수십억 개의 레코드 (1 년에 약 30 억 / 월)에 대해 작은 데이터 비트 (약 50-75 바이트)를 저장할 수 있어야합니다.

유일한 요구 사항은 GUID가 동일한 모든 레코드에 대한 빠른 삽입 및 빠른 조회와 .net에서 데이터 저장소에 액세스 할 수있는 기능입니다.

저는 SQL 서버 전문가이고 SQL Server 가이 작업을 수행 할 수 있다고 생각 하지만 BigTable, CouchDB 및 기타 nosql 솔루션에 대한 모든 논의를 통해 점점 더 전통적인 RDBS의 대안이 될 수 있습니다. 분산 쿼리 및 확장. 나는 cassandra를 시도했고 .net 라이브러리는 현재 컴파일되지 않거나 모두 변경 될 수 있습니다 (cassandra 자체와 함께).

사용 가능한 많은 nosql 데이터 저장소를 살펴 봤지만 강력한 프로덕션 준비 플랫폼으로서의 요구 사항을 충족하는 저장소를 찾을 수 없습니다.

.net에서 액세스 할 수 있도록 360 억 개의 작고 평평한 레코드를 저장해야한다면 무엇을 선택하고 그 이유는 무엇입니까?


~ 3.5TB의 데이터를 저장하고 약 1K / sec 24x7 삽입 및 지정되지 않은 속도로 쿼리하는 것도 SQL Server에서 가능하지만 더 많은 질문이 있습니다.

  • 이에 대한 가용성 요구 사항은 무엇입니까? 99.999 % 가동 시간 또는 95 % 충분합니까?
  • 어떤 신뢰성 요구 사항이 있습니까? 삽입물을 놓치면 백만 달러가 듭니까?
  • 어떤 복구 가능성 요구 사항이 있습니까? 하루의 데이터를 잃어버린 경우 문제가 있습니까?
  • 어떤 일관성 요구 사항이 있습니까? 쓰기가 다음 읽기에서 표시되도록 보장해야합니까?

내가 강조한 이러한 모든 요구 사항이 필요한 경우 제안하는로드는 어떤 기믹 (샤딩, 파티셔닝 등)을 시도하더라도 관계형 시스템, 모든 시스템에 대한 하드웨어 및 라이센스에 수백만 달러가들 것입니다. nosql 시스템은 정의상 이러한 모든 요구 사항을 충족하지 못합니다 .

따라서 이미 이러한 요구 사항 중 일부를 완화했습니다. Visual Guide to NoSQL Systems 의 'pick 2 of 3'패러다임을 기반으로 nosql 제품을 비교하는 멋진 시각적 가이드가 있습니다 .

nosql 비교

OP 코멘트 업데이트 후

SQL Server를 사용하면 간단하게 구현할 수 있습니다.

  • 단일 테이블 클러스터 (GUID, 시간) 키. 예, 조각화 될 예정 이지만 조각화는 미리 읽기에 영향을 미치고 미리 읽기는 중요한 범위 스캔에만 필요합니다. 특정 GUID 및 날짜 범위 만 쿼리하므로 조각화는 그다지 중요하지 않습니다. 예,은 와이드 키이므로 리프가 아닌 페이지는 키 밀도가 낮습니다. 예, 채우기 비율이 좋지 않습니다. 그리고 예, 페이지 분할이 발생할 수 있습니다. 이러한 문제에도 불구하고 요구 사항을 고려할 때 여전히 최상의 클러스터 키 선택입니다.
  • 자동 슬라이딩 창을 통해 만료 된 레코드를 효율적으로 삭제할 수 있도록 테이블을 시간별로 분할합니다 . GUID 클러스터링으로 인해 발생하는 빈약 한 채우기 비율 및 조각화를 제거하기 위해 지난달의 온라인 인덱스 파티션 재 구축으로이를 확장합니다.
  • 페이지 압축을 활성화합니다. 먼저 GUID별로 클러스터 된 키 그룹이 있기 때문에 GUID의 모든 레코드가 서로 옆에 있으므로 페이지 압축 이 사전 압축을 배포 할 수있는 좋은 기회를 제공 합니다 .
  • 로그 파일을위한 빠른 IO 경로가 필요합니다. 로그가 초당 1K 삽입을 유지하기위한 짧은 지연 시간이 아니라 높은 처리량에 관심이 있으므로 스트리핑 이 필수입니다.

분할 및 페이지 압축에는 각각 Enterprise Edition SQL Server가 필요하며 Standard Edition에서는 작동하지 않으며 둘 다 요구 사항을 충족하는 데 매우 중요합니다.

참고로 레코드가 프런트 엔드 웹 서버 팜에서 가져온 경우 각 웹 서버에 Express를 배치하고 백 엔드에 INSERT 대신 SEND로컬 연결 / 트랜잭션을 사용하여 백 엔드에 정보를 입력합니다. 웹 서버와 같은 위치에있는 Express에서. 이것은 솔루션에 훨씬 더 나은 가용성 스토리를 제공합니다.

그래서 이것이 SQL Server에서 수행하는 방법입니다. 좋은 소식은 직면하게 될 문제가 잘 이해되고 해결책이 알려져 있다는 것입니다. 이것이 반드시 Cassandra, BigTable 또는 Dynamo로 달성 할 수있는 것보다 더 낫다는 것을 의미하지는 않습니다. 나는 SQL이 아닌 일에 대해 더 많은 지식을 가진 사람에게 그들의 주장을 주장하도록 할 것입니다.

프로그래밍 모델, .Net 지원 등에 대해서는 언급 한 적이 없습니다. 솔직히 대규모 배포에는 관련이 없다고 생각합니다. 그들은 개발 프로세스에서 큰 차이를 만들지 만, 일단 배포되면 ORM 오버 헤드로 인해 성능이 저하되면 개발 속도는 중요하지 않습니다. :)


대중적인 믿음과는 달리 NoSQL은 성능이나 확장성에 관한 것이 아닙니다. 이는 주로 소위 Object-Relational 임피던스 불일치를 최소화하는 것이지만 수평 확장 성 대 RDBMS 의보다 일반적인 수직 확장 성에 관한 것이기도 합니다.

For the simple requirement of fasts inserts and fast lookups, almost any database product will do. If you want to add relational data, or joins, or have any complex transactional logic or constraints you need to enforce, then you want a relational database. No NoSQL product can compare.

If you need schemaless data, you'd want to go with a document-oriented database such as MongoDB or CouchDB. The loose schema is the main draw of these; I personally like MongoDB and use it in a few custom reporting systems. I find it very useful when the data requirements are constantly changing.

The other main NoSQL option is distributed Key-Value Stores such as BigTable or Cassandra. These are especially useful if you want to scale your database across many machines running commodity hardware. They work fine on servers too, obviously, but don't take advantage of high-end hardware as well as SQL Server or Oracle or other database designed for vertical scaling, and obviously, they aren't relational and are no good for enforcing normalization or constraints. Also, as you've noticed, .NET support tends to be spotty at best.

All relational database products support partitioning of a limited sort. They are not as flexible as BigTable or other DKVS systems, they don't partition easily across hundreds of servers, but it really doesn't sound like that's what you're looking for. They are quite good at handling record counts in the billions, as long as you index and normalize the data properly, run the database on powerful hardware (especially SSDs if you can afford them), and partition across 2 or 3 or 5 physical disks if necessary.

If you meet the above criteria, if you're working in a corporate environment and have money to spend on decent hardware and database optimization, I'd stick with SQL Server for now. If you're pinching pennies and need to run this on low-end Amazon EC2 cloud computing hardware, you'd probably want to opt for Cassandra or Voldemort instead (assuming you can get either to work with .NET).


Very few people work at the multi-billion row set size, and most times that I see a request like this on stack overflow, the data is no where near the size it is being reported as.

36 billion, 3 billion per month, thats roughly 100 million per day, 4.16 million an hour, ~70k rows per minute, 1.1k rows a second coming into the system, in a sustained manner for 12 months, assuming no down time.

Those figures are not impossible by a long margin, i've done larger systems, but you want to double check that is really the quantities you mean - very few apps really have this quantity.

In terms of storing / retrieving and quite a critical aspect you have not mentioned is aging the older data - deletion is not free.

The normal technology is look at is partitioning, however, the lookup / retrieval being GUID based would result in a poor performance, assuming you have to get every matching value across the whole 12 month period. You could place a clustered indexes on the GUID column will get your associated data clusterd for read / write, but at those quantities and insertion speed, the fragmentation will be far too high to support, and it will fall on the floor.

I would also suggest that you are going to need a very decent hardware budget if this is a serious application with OLTP type response speeds, that is by some approximate guesses, assuming very few overheads indexing wise, about 2.7TB of data.

In the SQL Server camp, the only thing that you might want to look at is the new parrallel data warehouse edition (madison) which is designed more for sharding out data and running parallel queries against it to provide high speed against large datamarts.


"I need to be able to store small bits of data (approximately 50-75 bytes) for billions of records (~3 billion/month for a year).

The only requirement is fast inserts and fast lookups for all records with the same GUID and the ability to access the data store from .net."

I can tell you from experience that this is possible in SQL Server, because I have done it in early 2009 ... and it's still operation to this day and quite fast.

The table was partitioned in 256 partitions, keep in mind this was 2005 SQL version ... and we did exactly what you're saying, and that is to store bits of info by GUID and retrieve by GUID quickly.

When i left we had around 2-3 billion records, and data retrieval was still quite good (1-2 seconds if get through UI, or less if on RDBMS) even though the data retention policy was just about to be instantiated.

So, long story short, I took the 8th char (i.e. somewhere in the middle-ish) from the GUID string and SHA1 hashed it and cast as tiny int (0-255) and stored in appropriate partition and used same function call when getting the data back.

ping me if you need more info...


The following article discusses the import and use of a 16 billion row table in Microsoft SQL. http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table.

From the article:

Here are some distilled tips from my experience:

  • The more data you have in a table with a defined clustered index, the slower it becomes to import unsorted records into it. At some point, it becomes too slow to be practical.
  • If you want to export your table to the smallest possible file, make it native format. This works best with tables containing mostly numeric columns because they’re more compactly represented in binary fields than character data. If all your data is alphanumeric, you won’t gain much by exporting it in native format. Not allowing nulls in the numeric fields can further compact the data. If you allow a field to be nullable, the field’s binary representation will contain a 1-byte prefix indicating how many bytes of data will follow.
  • You can’t use BCP for more than 2,147,483,647 records because the BCP counter variable is a 4-byte integer. I wasn’t able to find any reference to this on MSDN or the Internet. If your table consists of
    more than 2,147,483,647 records, you’ll have to export it in chunks
    or write your own export routine.
  • Defining a clustered index on a prepopulated table takes a lot of disk space. In my test, my log exploded to 10 times the original
    table size before completion.
  • When importing a large number of records using the BULK INSERT statement, include the BATCHSIZE parameter and specify how many
    records to commit at a time. If you don’t include this parameter,
    your entire file is imported as a single transaction, which
    requires a lot of log space.
  • The fastest way of getting data into a table with a clustered index is to presort the data first. You can then import it using the BULK
    INSERT statement with the ORDER parameter.

There is an unusual fact that seems to overlooked.

"Basically after inserting 30Mil rows in a day, I need to fetch all the rows with the same GUID (maybe 20 rows) and be reasonably sure I'd get them all back"

Needing only 20 columns, a non-clustered index on the GUID will work just fine. You could cluster on another column for data dispersion across partitions.

I have a question regarding the data insertion: How is it being inserted?

  • Is this a bulk insert on a certain schedule (per min, per hour, etc)?
  • What source is this data being pulled from (flat files, OLTP, etc)?

I think these need to be answered to help understand one side of the equation.


Amazon Redshift is a great service. It was not available when the question was originally posted in 2010, but it is now a major player in 2017. It is a column based database, forked from Postgres, so standard SQL and Postgres connector libraries will work with it.

It is best used for reporting purposes, especially aggregation. The data from a single table is stored on different servers in Amazon's cloud, distributed by on the defined table distkeys, so you rely on distributed CPU power.

So SELECTs and especially aggregated SELECTs are lightning fast. Loading large data should be preferably done with the COPY command from Amazon S3 csv files. The drawbacks are that DELETEs and UPDATEs are slower than usual, but that is why Redshift in not primarily a transnational database, but more of a data warehouse platform.


You can try using Cassandra or HBase, though you would need to read up on how to design the column families as per your use case. Cassandra provides its own query language but you need to use Java APIs of HBase to access the data directly. If you need to use Hbase then I recommend querying the data with Apache Drill from Map-R which is an Open Source project. Drill's query language is SQL-Compliant(keywords in drill have the same meaning they would have in SQL).


레코드를 일반 바이너리 파일 (GUID 당 하나의 파일)에 저장하는 것은 그보다 더 빠르지 않습니다.


MongoDB를 사용하고 guid를 샤딩 키로 사용할 수 있습니다. 즉, 여러 머신에 데이터를 배포 할 수 있지만 샤딩 키로 선택하기 때문에 선택하려는 데이터는 하나의 머신에만 있습니다.

MongoDb의 샤딩은 아직 생산 준비가되지 않았습니다.

참고 URL : https://stackoverflow.com/questions/2794736/best-data-store-for-billions-of-rows

반응형