concatenate_datasets loads all the data into memory
{'login': 'TaskManager91', 'id': 7063207, 'node_id': 'MDQ6VXNlcjcwNjMyMDc=', 'avatar_url': 'https://avatars.githubusercontent.com/u/7063207?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/TaskManager91', 'html_url': 'https://github.com/TaskManager91', 'followers_url': 'https://api.github.com/users/TaskManager91/followers', 'following_url': 'https://api.github.com/users/TaskManager91/following{/other_user}', 'gists_url': 'https://api.github.com/users/TaskManager91/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/TaskManager91/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/TaskManager91/subscriptions', 'organizations_url': 'https://api.github.com/users/TaskManager91/orgs', 'repos_url': 'https://api.github.com/users/TaskManager91/repos', 'events_url': 'https://api.github.com/users/TaskManager91/events{/privacy}', 'received_events_url': 'https://api.github.com/users/TaskManager91/received_events', 'type': 'User', 'site_admin': False}
[{'id': 1935892857, 'node_id': 'MDU6TGFiZWwxOTM1ODkyODU3', 'url': 'https://api.github.com/repos/huggingface/datasets/labels/bug', 'name': 'bug', 'color': 'd73a4a', 'default': True, 'description': "Something isn't working"}]
{'login': 'lhoestq', 'id': 42851186, 'node_id': 'MDQ6VXNlcjQyODUxMTg2', 'avatar_url': 'https://avatars.githubusercontent.com/u/42851186?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/lhoestq', 'html_url': 'https://github.com/lhoestq', 'followers_url': 'https://api.github.com/users/lhoestq/followers', 'following_url': 'https://api.github.com/users/lhoestq/following{/other_user}', 'gists_url': 'https://api.github.com/users/lhoestq/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/lhoestq/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/lhoestq/subscriptions', 'organizations_url': 'https://api.github.com/users/lhoestq/orgs', 'repos_url': 'https://api.github.com/users/lhoestq/repos', 'events_url': 'https://api.github.com/users/lhoestq/events{/privacy}', 'received_events_url': 'https://api.github.com/users/lhoestq/received_events', 'type': 'User', 'site_admin': False}
[{'login': 'lhoestq', 'id': 42851186, 'node_id': 'MDQ6VXNlcjQyODUxMTg2', 'avatar_url': 'https://avatars.githubusercontent.com/u/42851186?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/lhoestq', 'html_url': 'https://github.com/lhoestq', 'followers_url': 'https://api.github.com/users/lhoestq/followers', 'following_url': 'https://api.github.com/users/lhoestq/following{/other_user}', 'gists_url': 'https://api.github.com/users/lhoestq/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/lhoestq/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/lhoestq/subscriptions', 'organizations_url': 'https://api.github.com/users/lhoestq/orgs', 'repos_url': 'https://api.github.com/users/lhoestq/repos', 'events_url': 'https://api.github.com/users/lhoestq/events{/privacy}', 'received_events_url': 'https://api.github.com/users/lhoestq/received_events', 'type': 'User', 'site_admin': False}]
['Therefore, when I try to concatenate larger datasets (5x 35GB data sets) I also get an out of memory error, since over 90GB of swap space was used at the time of the crash:\r\n\r\n```\r\n---------------------------------------------------------------------------\r\nMemoryError                               Traceback (most recent call last)\r\n<ipython-input-6-9766d77530b9> in <module>\r\n     20         print(file_name)\r\n     21         cv_batch = load_from_disk(file_name)\r\n---> 22         cv_sampled_train = concatenate_datasets([cv_sampled_train, cv_batch])\r\n     23 \r\n     24 print("Saving to disk!")\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\datasets\\arrow_dataset.py in concatenate_datasets(dsets, info, split, axis)\r\n   2891 \r\n   2892     # Concatenate tables\r\n-> 2893     table = concat_tables([dset._data for dset in dsets if len(dset._data) > 0], axis=axis)\r\n   2894     table = update_metadata_with_features(table, None)\r\n   2895 \r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\datasets\\table.py in concat_tables(tables, axis)\r\n    837     if len(tables) == 1:\r\n    838         return tables[0]\r\n--> 839     return ConcatenationTable.from_tables(tables, axis=axis)\r\n    840 \r\n    841 \r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\datasets\\table.py in from_tables(cls, tables, axis)\r\n    697             return result\r\n    698 \r\n--> 699         blocks = to_blocks(tables[0])\r\n    700         for table in tables[1:]:\r\n    701             table_blocks = to_blocks(table)\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\datasets\\table.py in to_blocks(table)\r\n    669                 return [[InMemoryTable(table)]]\r\n    670             elif isinstance(table, ConcatenationTable):\r\n--> 671                 return copy.deepcopy(table.blocks)\r\n    672             else:\r\n    673                 return [[table]]\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_list(x, memo, deepcopy)\r\n    203     append = y.append\r\n    204     for a in x:\r\n--> 205         append(deepcopy(a, memo))\r\n    206     return y\r\n    207 d[list] = _deepcopy_list\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_list(x, memo, deepcopy)\r\n    203     append = y.append\r\n    204     for a in x:\r\n--> 205         append(deepcopy(a, memo))\r\n    206     return y\r\n    207 d[list] = _deepcopy_list\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    151             copier = getattr(x, "__deepcopy__", None)\r\n    152             if copier is not None:\r\n--> 153                 y = copier(memo)\r\n    154             else:\r\n    155                 reductor = dispatch_table.get(cls)\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\datasets\\table.py in __deepcopy__(self, memo)\r\n    143         # by adding it to the memo, self.table won\'t be copied\r\n    144         memo[id(self.table)] = self.table\r\n--> 145         return _deepcopy(self, memo)\r\n    146 \r\n    147     def __getstate__(self):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\datasets\\table.py in _deepcopy(x, memo)\r\n     62     memo[id(x)] = result\r\n     63     for k, v in x.__dict__.items():\r\n---> 64         setattr(result, k, copy.deepcopy(v, memo))\r\n     65     return result\r\n     66 \r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_list(x, memo, deepcopy)\r\n    203     append = y.append\r\n    204     for a in x:\r\n--> 205         append(deepcopy(a, memo))\r\n    206     return y\r\n    207 d[list] = _deepcopy_list\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    170                     y = x\r\n    171                 else:\r\n--> 172                     y = _reconstruct(x, memo, *rv)\r\n    173 \r\n    174     # If is its own copy, don\'t memoize.\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)\r\n    262     if deep and args:\r\n    263         args = (deepcopy(arg, memo) for arg in args)\r\n--> 264     y = func(*args)\r\n    265     if deep:\r\n    266         memo[id(x)] = y\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in <genexpr>(.0)\r\n    261     deep = memo is not None\r\n    262     if deep and args:\r\n--> 263         args = (deepcopy(arg, memo) for arg in args)\r\n    264     y = func(*args)\r\n    265     if deep:\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_list(x, memo, deepcopy)\r\n    203     append = y.append\r\n    204     for a in x:\r\n--> 205         append(deepcopy(a, memo))\r\n    206     return y\r\n    207 d[list] = _deepcopy_list\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    170                     y = x\r\n    171                 else:\r\n--> 172                     y = _reconstruct(x, memo, *rv)\r\n    173 \r\n    174     # If is its own copy, don\'t memoize.\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)\r\n    262     if deep and args:\r\n    263         args = (deepcopy(arg, memo) for arg in args)\r\n--> 264     y = func(*args)\r\n    265     if deep:\r\n    266         memo[id(x)] = y\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in <genexpr>(.0)\r\n    261     deep = memo is not None\r\n    262     if deep and args:\r\n--> 263         args = (deepcopy(arg, memo) for arg in args)\r\n    264     y = func(*args)\r\n    265     if deep:\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_tuple(x, memo, deepcopy)\r\n    208 \r\n    209 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):\r\n--> 210     y = [deepcopy(a, memo) for a in x]\r\n    211     # We\'re not going to put the tuple in the memo, but it\'s still important we\r\n    212     # check for it, in case the tuple contains recursive mutable structures.\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in <listcomp>(.0)\r\n    208 \r\n    209 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):\r\n--> 210     y = [deepcopy(a, memo) for a in x]\r\n    211     # We\'re not going to put the tuple in the memo, but it\'s still important we\r\n    212     # check for it, in case the tuple contains recursive mutable structures.\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_list(x, memo, deepcopy)\r\n    203     append = y.append\r\n    204     for a in x:\r\n--> 205         append(deepcopy(a, memo))\r\n    206     return y\r\n    207 d[list] = _deepcopy_list\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_tuple(x, memo, deepcopy)\r\n    208 \r\n    209 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):\r\n--> 210     y = [deepcopy(a, memo) for a in x]\r\n    211     # We\'re not going to put the tuple in the memo, but it\'s still important we\r\n    212     # check for it, in case the tuple contains recursive mutable structures.\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in <listcomp>(.0)\r\n    208 \r\n    209 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):\r\n--> 210     y = [deepcopy(a, memo) for a in x]\r\n    211     # We\'re not going to put the tuple in the memo, but it\'s still important we\r\n    212     # check for it, in case the tuple contains recursive mutable structures.\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    144     copier = _deepcopy_dispatch.get(cls)\r\n    145     if copier is not None:\r\n--> 146         y = copier(x, memo)\r\n    147     else:\r\n    148         if issubclass(cls, type):\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in _deepcopy_list(x, memo, deepcopy)\r\n    203     append = y.append\r\n    204     for a in x:\r\n--> 205         append(deepcopy(a, memo))\r\n    206     return y\r\n    207 d[list] = _deepcopy_list\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\copy.py in deepcopy(x, memo, _nil)\r\n    159                     reductor = getattr(x, "__reduce_ex__", None)\r\n    160                     if reductor is not None:\r\n--> 161                         rv = reductor(4)\r\n    162                     else:\r\n    163                         reductor = getattr(x, "__reduce__", None)\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\pyarrow\\io.pxi in pyarrow.lib.Buffer.__reduce_ex__()\r\n\r\nC:\\ProgramData\\Anaconda3\\lib\\site-packages\\pyarrow\\io.pxi in pyarrow.lib.Buffer.to_pybytes()\r\n\r\nMemoryError: \r\n\r\n```'
 'Hi ! this looks like an important issue. Let me try to reproduce this.\r\nCc @samsontmr this might be related to the memory issue you have in #2134 '
 '@lhoestq Just went to open a similar issue.\r\n\r\nIt seems like deep copying (tested on master) the dataset object writes the table\'s record batches (`dset._data._batches`) into RAM.\r\n\r\nTo find the bug, I modified the `_deepcopy` function in `table.py` as follows:\r\n```python\r\ndef _deepcopy(x, memo: dict):\r\n    """deepcopy a regular class instance"""\r\n    import psutil # pip install this package\r\n    import time\r\n    cls = x.__class__\r\n    result = cls.__new__(cls)\r\n    memo[id(x)] = result\r\n    for k, v in x.__dict__.items():\r\n        print("="* 50)\r\n        print("Current memory:", psutil.virtual_memory().percent)\r\n        print(f"Saving object {k} with value {v}")\r\n        setattr(result, k, copy.deepcopy(v, memo))\r\n        time.sleep(5)\r\n        print("Memory after copy:", psutil.virtual_memory().percent)\r\n    return result\r\n```\r\nTest script:\r\n```python\r\nimport copy\r\nfrom datasets import load_dataset\r\nbk = load_dataset("bookcorpus", split="train")\r\nbk_copy = copy.deepcopy(bk)\r\n```'
 "Thanks for the insights @mariosasko ! I'm working on a fix.\r\nSince this is a big issue I'll make a patch release as soon as this is fixed"
 'Hi @samsontmr @TaskManager91 the fix is on the master branch, feel free to install `datasets` from source and let us know if you still have issues'
 'We just released `datasets` 1.6.2 that includes the fix :)'
 'thanks it works like a charm! :)']
## Describe the bug
When I try to concatenate 2 datasets (10GB each) , the entire data is loaded into memory instead of being written directly to disk.

Interestingly, this happens when trying to save the new dataset to disk or concatenating it again.

![image](https://user-images.githubusercontent.com/7063207/116420321-2b21b480-a83e-11eb-9006-8f6ca729fb6f.png)


## Steps to reproduce the bug
```python
from datasets import concatenate_datasets, load_from_disk

test_sampled_pro = load_from_disk("test_sampled_pro")
val_sampled_pro = load_from_disk("val_sampled_pro")

big_set = concatenate_datasets([test_sampled_pro, val_sampled_pro])

# Loaded to memory
big_set.save_to_disk("big_set")

# Loaded to memory
big_set = concatenate_datasets([big_set, val_sampled_pro])
```

## Expected results
The data should be loaded into memory in batches and then saved directly to disk.

## Actual results
The entire data set is loaded into the memory and then saved to the hard disk.

## Versions
Paste the output of the following code:
```python
- Datasets: 1.6.1
- Python: 3.8.8 (default, Apr 13 2021, 19:58:26) 
[GCC 7.3.0]
- Platform: Linux-5.4.72-microsoft-standard-WSL2-x86_64-with-glibc2.10
```

{'url': 'https://api.github.com/repos/huggingface/datasets/issues/2276/reactions', 'total_count': 0, '+1': 0, '-1': 0, 'laugh': 0, 'hooray': 0, 'confused': 0, 'heart': 0, 'rocket': 0, 'eyes': 0}