У меня есть большая секционированная таблица.Ключи разделов определяются как длинный список прерывистых идентификаторов.Например:
Partition of: foo_partitioned FOR VALUES IN (1733, 1731, 1800, 1732, 1799, 1798, 1804, 1803, 1802, 1801, 1797, 1796, 1795, 1794, 1793, 1792, 1791, 1790, 1789, 1788, 1787, 1786,
1785, 1784, 1783, 1715, 1714, 1713, 1712, 1711, 1710, 1709, 1708, 1707, 1706, 1705, 1704, 1703, 1702, 1701, 1700, 1699, 1698, 1697, 1696, 1695, 1694, 1693, 1692, 1691, 1689,
1688, 1687, 1686, 1685, 1684, 1683, 1682, 1681, 1680, 1679, 1658, 1657, 1656, 1655, 1654, 1653, 1652, 1651, 1650, 1649, 1648, 1647, 1646, 1645, 1644, 1643, 1642, 1641, 1640,
1639, 1638, 1637, 1636, 1635, 1634, 1633, 1632, 1631, 1630, 1629, 1628, 1627, 1626, 1625, 1624, 1623, 1622, 1581, 1580, 1579, 1578, 1577, 1569, 1568, 1567, 1547, 1546, 1545,
1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1808, 1809, 1810, 1811, 1888, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833,
1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862,
1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1889, 1890, 1891, 1892,
1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921,
1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953,
1954, 1955, 1956, 1957, 1959, 1960, 1961)
Partition constraint: ((bar_id IS NOT NULL) AND (bar_id = ANY (ARRAY[1733, 1731, 1800, 1732, 1799, 1798, 1804, 1803, 1802, 1801, 1797, 1796, 1795, 1794, 1793, 1792, 1791, 1790,
1789, 1788, 1787, 1786, 1785, 1784, 1783, 1715, 1714, 1713, 1712, 1711, 1710, 1709, 1708, 1707, 1706, 1705, 1704, 1703, 1702, 1701, 1700, 1699, 1698, 1697, 1696, 1695, 1694,
1693, 1692, 1691, 1689, 1688, 1687, 1686, 1685, 1684, 1683, 1682, 1681, 1680, 1679, 1658, 1657, 1656, 1655, 1654, 1653, 1652, 1651, 1650, 1649, 1648, 1647, 1646, 1645, 1644,
1643, 1642, 1641, 1640, 1639, 1638, 1637, 1636, 1635, 1634, 1633, 1632, 1631, 1630, 1629, 1628, 1627, 1626, 1625, 1624, 1623, 1622, 1581, 1580, 1579, 1578, 1577, 1569, 1568,
1567, 1547, 1546, 1545, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1808, 1809, 1810, 1811, 1888, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829,
1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858,
1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887,
1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917,
1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949,
1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1959, 1960, 1961])))
При выполнении объяснения для запроса, который соответствует этому точному списку значений с помощью предложения IN, планировщик пытается просканировать все разделы.Даже когда вы делаете что-то простое, например, просматриваете одно значение:
select * from foo_partitioned where bar_id=1733;
Планировщик запросов проверяет каждый раздел.
Append (cost=102.95..365378.32 rows=378224 width=36)
-> Bitmap Heap Scan on foo_partitioned_8 (cost=102.95..3508.07 rows=4571 width=36)
Recheck Cond: (bar_id = 1732)
-> Bitmap Index Scan on uq_foo_partitioned_8 (cost=0.00..101.81 rows=4571 width=0)
Index Cond: (bar_id = 1732)
-> Index Scan using uq_foo_partitioned_16 on foo_partitioned_16 (cost=0.56..55328.46 rows=62937 width=36)
Index Cond: (bar_id = 1732)
-> Bitmap Heap Scan on foo_partitioned_25 (cost=1.30..6.52 rows=6 width=36)
Recheck Cond: (bar_id = 1732)
-> Bitmap Index Scan on uq_foo_partitioned_25 (cost=0.00..1.30 rows=6 width=0)
Index Cond: (bar_id = 1732)
-> Bitmap Heap Scan on foo_partitioned_26 (cost=1.30..6.52 rows=6 width=36)
Recheck Cond: (bar_id = 1732)
-> Bitmap Index Scan on uq_foo_partitioned_26 (cost=0.00..1.30 rows=6 width=0)
Index Cond: (bar_id = 1732)
-> Bitmap Heap Scan on foo_partitioned_27 (cost=1.30..6.52 rows=6 width=36)
Recheck Cond: (bar_id = 1732)
-> Bitmap Index Scan on uq_foo_partitioned_27 (cost=0.00..1.30 rows=6 width=0)
Index Cond: (bar_id = 1732)
-> Bitmap Heap Scan on foo_partitioned_28 (cost=1.30..6.52 rows=6 width=36)
Recheck Cond: (bar_id = 1732)
-> Bitmap Index Scan on uq_foo_partitioned_28 (cost=0.00..1.30 rows=6 width=0)
Index Cond: (bar_id = 1732)
-> Bitmap Heap Scan on foo_partitioned_29 (cost=347.37..14554.48 rows=15528 width=36)
Recheck Cond: (bar_id = 1732)
...
Есть ли лучший способ а) определить такие таблицычто на самом деле используется исключение ограничений (у меня установлено разделение) или б) напишите запрос, чтобы на самом деле использовалось исключение ограничений?
Я попытался немного взглянуть на код но, кажется, за меня.
РЕДАКТИРОВАТЬ
Я провел некоторое время, экспериментируя с альтернативным решением.Я сделал вторичный ключ в качестве потенциального первичного ключа, который заставил все столбцы быть смежными и в известном диапазоне для каждого раздела.Затем я создал вторую сопоставимую многораздельную таблицу, используя разделенное ранжирование, чтобы провести некоторое тестирование.
Некоторые вещи, которые я обнаружил:
- Использование диапазона или двух в выражении where (
WHERE 50000 <= bar_id AND 50500 < bar_id
) вызывает исключение ограничения - Использование большого * where "list", будь то в виде простого выражения
IN
или IN (VALUES...)
, не вызывает исключение ограничения - * Однако при использовании спискаиз 100 или менее значений в предложении
IN
вызывает исключение ограничения.Более того, и кое-что еще появляется в планировщике внутренних запросов PostgreSQL.
Другие вещи, которые я также пробовал, были объединяющими объединение порциями запросов, сгруппированных в группы по 100 баров, что вызывает исключение ограничений для каждогозапрос подмножества, но не такой быстрый, как использование диапазона X
При этом обе версии были> в 10 раз быстрее, чем раньше, поэтому в некотором смысле миссия выполнена.Я планирую использовать логику своего приложения для создания умных диапазонов, а не использовать порции по 100, возможно, если у меня нет очень разрозненных bar_ids (что я считаю маловероятным, TBD).
Надеюсь, это поможет другим, желающим использовать разбиение PG.
Если кто-либо, работающий с PG, может прокомментировать, что происходит как с предыдущей версией 'list', так и с диапазоном со списком> 100, этобыло бы очень полезно и интересно.
Обратите внимание, что я предполагаю - для разбиения на основе списка - что использование списка из 100 или менее в разделе определений может позволить исключение ограничения для включенияТак как логика, которая предотвращает это в тестировании разделов диапазона, который я делал, может быть разделена и логикой сокращения разделов, где она просто сдается независимо от того, что, если определение списка превышает 100 элементов.