2013-07-26 4 views
5

Возможно ли получить максимальное количество столбцов, поддерживаемых с sqlite3 во время выполнения? Это ограничение базы данных устанавливается с переменной времени компиляции SQLITE_MAX_COLUMN (см. limits). По умолчанию обычно 2000 столбцов.Определить максимальное количество столбцов из sqlite3

Я ищу что-то доступное из интерфейса Python или SQL.

ответ

7

Это представляется невозможным в практическом плане (т. Е. Без очень дорогого подхода грубой силы вдоль линий довольно блестящего ответа dan04).

Источник (1, 2) для sqlite3 модуля не содержит ссылок ни на SQLITE_MAX_COLUMN или во время компиляции пределы в целом; также нет никакого способа получить к ним доступ из интерфейса SQL.

UPDATE:

Простая модификация dan04's solution использовать бинарный поиск ускоряет вещи значительно:

import sqlite3 

def max_columns(): 
    db = sqlite3.connect(':memory:') 
    low = 1 
    high = 32767 # hard limit <http://www.sqlite.org/limits.html> 
    while low < high - 1: 
     guess = (low + high) // 2 
     try: 
      db.execute('CREATE TABLE T%d (%s)' % (
       guess, ','.join('C%d' % i for i in range(guess)) 
      )) 
     except sqlite3.DatabaseError as ex: 
      if 'too many columns' in str(ex): 
       high = guess 
      else: 
       raise 
     else: 
      low = guess 
    return low 

Выполнение кода выше через timeit.repeat():

>>> max_columns() 
2000 
>>> import timeit 
>>> timeit.repeat(
...  "max_columns()", 
...  setup="from __main__ import max_columns", 
...  number=50 
...) 
[10.347190856933594, 10.0917809009552, 10.320987939834595] 

.. , который достигает среднего времени выполнения 30,76/150 = 0,205 секунд (на четырехъядерном процессоре 2,6 ГГц re machine) - не совсем быстрый, но, вероятно, более полезный, чем 15-20 секунд «пинайте его, пока он не сломает» метод подсчета с одного.

+0

Удивительный подход, +1! –

3

простой, но неэффективный способ сделать это из Python:

import itertools 
import sqlite3 

db = sqlite3.connect(':memory:') 
try: 
    for num_columns in itertools.count(1): 
     db.execute('CREATE TABLE T%d (%s)' % (num_columns, ','.join('C%d' % i for i in range(num_columns)))) 
except sqlite3.DatabaseError as ex: 
    if 'too many columns' in str(ex): 
     print('Max columns = %d' % (num_columns - 1)) 
+1

Ха! Это довольно изобретательно. +1 для чистой жестокости, даже если на моей машине требуется почти 20 секунд :-) –

+1

@ZeroPiraeus: Есть оптимизации, которые вы могли бы выполнить. Например, использование экспоненциального роста для поиска верхней границы и деления пополам для определения нижней границы приведет к уменьшению числа таблиц, созданных с N до O (log N). Вы также можете начать с проверки 2000 и 2001 годов, исходя из предположения, что большинство SQLite-сборок будут использовать только опцию 'SQLITE_MAX_COLUMN' по умолчанию. – dan04

+0

И похоже, что вы поняли, что в то же время я сделал :-) – dan04